summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rwxr-xr-x1-prereqs.sh251
-rwxr-xr-x2-jenkins.sh345
-rwxr-xr-x3-repositories.sh110
-rwxr-xr-x4-uncron.sh90
-rwxr-xr-x5-docker-jobs.sh59
-rwxr-xr-x6-provision-project-jobs.sh45
-rwxr-xr-x7-build-project-jobs.sh55
-rwxr-xr-x8-nginx.sh81
-rw-r--r--helper-logic584
-rw-r--r--install-files/daemon.json5
-rw-r--r--install-files/dummy0.interface4
-rwxr-xr-xinstall-files/gpg-script.sh24
-rw-r--r--install-files/nginx-site21
-rw-r--r--install-files/org.jenkinsci.plugins.docker.workflow.declarative.GlobalConfig.xml5
-rw-r--r--install-files/org.jenkinsci.plugins.workflow.libs.GlobalLibraries.xml4
-rwxr-xr-xinstall-files/ssh-script.sh25
-rwxr-xr-xinstall-files/uncron-add21
-rwxr-xr-xinstall-files/uncron-script.sh35
-rw-r--r--install-files/uncron.service16
-rw-r--r--jobs/docker-container-jobs.json14
-rw-r--r--jobs/jobTemplate.xml (renamed from jenkins-scripts/jobTemplate.xml)0
-rw-r--r--jobs/project-jobs.json443
23 files changed, 2238 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..352e7ce
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+jenkins-cli.jar \ No newline at end of file
diff --git a/1-prereqs.sh b/1-prereqs.sh
new file mode 100755
index 0000000..781e70d
--- /dev/null
+++ b/1-prereqs.sh
@@ -0,0 +1,251 @@
+#!/usr/bin/env bash
+
+source ./helper-logic
+
+# Clear the screen and print the header
+PrintHeader
+
+# Ensure we are running as root
+EnsureRoot
+
+#region Update apt sources
+Run "apt-get update" \
+ "Updating apt sources..." \
+ "Failed to update apt sources." \
+ "Updated apt sources."
+#endregion
+
+#region Download cURL
+if [ $(dpkg-query -W -f='${Status}' curl 2>/dev/null | grep -c "ok installed") -eq 1 ]; then
+ PrintOkIndicator "cURL is already installed."
+else
+ function DownloadCurl {
+ apt-get install curl -y
+ }
+
+ Run "DownloadCurl" \
+ "Installing cURL..." \
+ "Failed to install cURL." \
+ "Installed cURL."
+fi
+#endregion
+
+#region Set up sources.list.d files for Jenkins
+if [ -f /etc/apt/sources.list.d/jenkins.list ]; then
+ PrintOkIndicator "Jenkins sources.list.d has already been set up."
+else
+ function SetupJenkinsSourceListD {
+ curl -s -S https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key -o /usr/share/keyrings/jenkins-keyring.asc --fail-with-body
+ echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc]" https://pkg.jenkins.io/debian-stable binary/ | tee /etc/apt/sources.list.d/jenkins.list
+ }
+
+ Run "SetupJenkinsSourceListD" \
+ "Setting up Jenkins sources.list.d files..." \
+ "Failed to download or set up Jenkins sources.list.d files." \
+ "Jenkins sources.list.d files has been set up."
+fi
+#endregion
+
+#region Set up sources.list.d files for Docker
+if [ -f /etc/apt/sources.list.d/docker.list ]; then
+ PrintOkIndicator "Docker sources.list.d has already been set up."
+else
+ function SetupDockerSourceListD {
+ curl -s -S https://download.docker.com/linux/debian/gpg -o /usr/share/keyrings/docker.asc --fail-with-body
+ echo "deb [signed-by=/usr/share/keyrings/docker.asc]" https://download.docker.com/linux/debian bookworm stable | tee /etc/apt/sources.list.d/docker.list
+ }
+
+ Run "SetupDockerSourceListD" \
+ "Setting up Docker sources.list.d files..." \
+ "Failed to download or set up Docker sources.list.d files." \
+ "Docker sources.list.d files has been set up."
+fi
+#endregion
+
+#region Update apt sources again
+Run "apt-get update" \
+ "Updating apt sources..." \
+ "Failed to update apt sources." \
+ "Updated apt sources."
+#endregion
+
+#region Jenkins user and group
+if grep -q "^jenkins:" /etc/group; then
+ PrintOkIndicator "Jenkins group already exist."
+else
+ function CreateJenkinsGroup {
+ groupadd --gid 1006 jenkins
+ }
+
+ Run "CreateJenkinsGroup" \
+ "Creating jenkins group with GID 1006..." \
+ "Failed to create jenkins group." \
+ "Created jenkins group."
+fi
+
+if id -u jenkins > /dev/null 2>&1; then
+ PrintOkIndicator "Jenkins user already exist."
+else
+ function CreateJenkinsUser {
+ useradd --comment Jenkins --shell /bin/bash --uid 1006 --gid 1006 --home-dir /var/lib/jenkins jenkins
+ }
+
+ Run "CreateJenkinsUser" \
+ "Creating jenkins user with UID 1006..." \
+ "Failed to create jenkins user." \
+ "Created jenkins user."
+fi
+#endregion
+
+#region Install needed tools
+declare -A tools
+tools["Git"]="git"
+tools["GnuPG"]="gpg"
+tools["SSH"]="openssh-server openssh-client openssh-sftp-server"
+tools["Reprepro"]="reprepro"
+tools["XMLStarlet"]="xmlstarlet"
+tools["Jq"]="jq"
+tools["NGINX"]="nginx"
+tools["Java"]="openjdk-17-jre fontconfig"
+tools["Docker"]="docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin"
+tools["OCaml"]="opam ocaml socat"
+tools["Jenkins"]="jenkins"
+tools["AptCacherNg"]="apt-cacher-ng"
+
+for key in "${!tools[@]}"
+do
+ VALUES=$(sed -e 's/ /\n/g' <<< "${tools[$key]}")
+
+ ALL_INSTALLED="true"
+
+ for package in $VALUES; do
+ if [ $(dpkg-query -W -f='${Status}' $package 2>/dev/null | grep -c "ok installed") -ne 1 ]; then
+ ALL_INSTALLED="false"
+ fi
+ done
+
+ if [[ $ALL_INSTALLED == "true" ]]; then
+ PrintOkIndicator "$key is already installed."
+ else
+ function InstallTool {
+ DEBIAN_FRONTEND=noninteractive apt-get -yq install $@
+ }
+
+ Run "InstallTool ${tools[$key]}" \
+ "Installing $key..." \
+ "Failed to install $key." \
+ "Installed $key."
+ fi
+done
+#endregion
+
+#region Add jenkins user to docker group
+if grep "^docker:" /etc/group |grep -q ":jenkins"; then
+ PrintOkIndicator "Jenkins user is already added to the Docker group."
+else
+ function AddJenkinsUserToDockerGroup {
+ usermod -a -G docker jenkins
+ }
+
+ function RestartJenkins {
+ systemctl restart jenkins.service
+ }
+
+ Run "AddJenkinsUserToDockerGroup" \
+ "Adding Jenkins user to Docker group..." \
+ "Failed to add Jenkins user to Docker group." \
+ "Added Jenkins user to Docker group."
+
+ Run "RestartJenkins" \
+ "Restarting Jenkins..." \
+ "Failed to restart Jenkins." \
+ "Restarted Jenkins."
+fi
+#endregion
+
+#region Add dummy0 interface
+if [ -f /etc/network/interfaces.d/dummy0.interface ]; then
+ PrintOkIndicator "Network interface dummy0 has already been configured."
+else
+ function CopyInterfaceFile {
+ cp ./install-files/dummy0.interface /etc/network/interfaces.d
+ }
+
+ Run "CopyInterfaceFile" \
+ "Configuring network interface dummy0..." \
+ "Failed to configure network interface dummy0." \
+ "Network interface dummy0 has been configured."
+fi
+#endregion
+
+#region Start network interface dummy0
+if ip a show dummy0 2>/dev/null > /dev/null; then
+ PrintOkIndicator "Network interface dummy0 is already started."
+else
+ Run "ifup dummy0" \
+ "Starting network interface dummy0..." \
+ "Failed to start network interface dummy0." \
+ "Started network interface dummy0."
+fi
+#endregion
+
+#region Install Docker Registry
+if [ -f /etc/docker/daemon.json ]; then
+ PrintOkIndicator "Docker Registry has already been configured."
+else
+ function CreateDockerRegistryConfig {
+ cp ./install-files/daemon.json /etc/docker/
+ }
+
+ function RestartDocker {
+ systemctl restart docker.service
+ }
+
+ Run "CreateDockerRegistryConfig" \
+ "Configuring Docker Registry..." \
+ "Failed to configure Docker Registry." \
+ "Docker registry has been configured."
+
+ Run "RestartDocker" \
+ "Restarting Docker..." \
+ "Failed to restart Docker." \
+ "Restarted Docker."
+fi
+#endregion
+
+#region Pull image if it doesn't exist locally.
+if docker image inspect registry:2.7 > /dev/null 2>&1; then
+ PrintOkIndicator "Docker Registry image has already been pulled."
+else
+ function PullDockerRegistryImage {
+ docker pull registry:2.7
+ }
+
+ Run "PullDockerRegistryImage" \
+ "Pulling Docker Registry image..." \
+ "Failed to pull Docker Registry image." \
+ "Docker Registry image has been pulled."
+fi
+#endregion
+
+#region Start Docker Registry
+if docker container inspect registry > /dev/null 2>&1; then
+ PrintOkIndicator "Docker Registry is already running."
+else
+ function StartDockerRegistry {
+ docker run -d -p 5000:5000 --restart always --name registry registry:2.7
+ }
+
+ Run "StartDockerRegistry" \
+ "Starting Docker Registry..." \
+ "Failed to start Docker Registry." \
+ "Docker Registry has been started."
+fi
+#endregion
+
+echo
+echo "Part 1 of the installer is now done."
+echo "Please run part two to set up Jenkins."
+
+# Create marker file
+CreateMarkerFile 1 \ No newline at end of file
diff --git a/2-jenkins.sh b/2-jenkins.sh
new file mode 100755
index 0000000..b8bcf77
--- /dev/null
+++ b/2-jenkins.sh
@@ -0,0 +1,345 @@
+#!/usr/bin/env bash
+
+source ./helper-logic
+
+# Clear the screen and print the header
+PrintHeader
+
+# Ensure we are running as root
+EnsureRoot
+
+# Ensure stage 1 is complete
+EnsureStageIsComplete 1
+
+# Define variables
+INITIAL_PASSWORD_FILE="/var/lib/jenkins/secrets/initialAdminPassword"
+NETWORK_INTERFACES=`ls /sys/class/net/ -1 |grep -v -w "lo" |grep -v docker |grep -v dummy |grep -v veth`
+
+#region Run SSH script
+cp install-files/ssh-script.sh /var/lib/jenkins
+chown jenkins:jenkins /var/lib/jenkins/ssh-script.sh
+
+# This script create the SSH key, adds it to the trusted keys and trusts the host itself.
+echo "Running SSH script as jenkins user..."
+runuser -l jenkins -c "./ssh-script.sh"
+echo
+
+rm /var/lib/jenkins/ssh-script.sh > /dev/null 2>&1
+#endregion
+
+#region Run GnuPG script
+cp install-files/gpg-script.sh /var/lib/jenkins
+chown jenkins:jenkins /var/lib/jenkins/gpg-script.sh
+
+# This script generates the GnuPG key pair.
+echo "Running GnuPG script as jenkins user..."
+runuser -l jenkins -c "./gpg-script.sh"
+echo
+
+rm /var/lib/jenkins/gpg-script.sh > /dev/null 2>&1
+#endregion
+
+#region Initial Jenkins user setup and ask for credentials
+function PrintUrls {
+ echo
+ for INTERFACE in $NETWORK_INTERFACES; do
+ IP_ADDRESS=`ifconfig $INTERFACE | grep 'inet '| cut -d: -f2 | awk '{ print $2}'`
+ if [[ $IP_ADDRESS != "" ]]; then
+ echo -e "${GREEN}http://$IP_ADDRESS:8080$1${NOCOLOR}"
+ fi
+ done
+ echo
+}
+
+if [ -f $INITIAL_PASSWORD_FILE ]; then
+ # This is the first run (or the previous run never made it to finish creating an admin user).
+ INITIAL_PASSWORD=`cat /var/lib/jenkins/secrets/initialAdminPassword`
+
+ echo -e "Please open a web browser, and go to one of these URLs:"
+ PrintUrls
+ echo -e "Then, login using this password: ${GREEN}$INITIAL_PASSWORD${NOCOLOR}"
+ echo
+ read -p "Press enter when you are logged on."
+ echo
+ echo -e "Now click the \"${GREEN}Install suggested plugins${NOCOLOR}\" button"
+ echo
+ read -p "Press enter when the plugins are done installing."
+ echo
+ echo "When prompted, create the first admin user."
+ echo
+ read -p "Please enter the username you choose here, and press enter: " USERNAME
+ echo
+ echo "Just leave the default url, and continue until you are greeted with the Welcome page."
+ echo
+else
+ # This is a re-run, so the admin user has already been created.
+ if ([ ! -f $USERNAME_FILE ] || [ ! -f $TOKEN_FILE ]); then
+ # There is no USERNAME_FILE or TOKEN_FILE, so we ask the user to provide the username.
+ echo -e "Please open a web browser, and go to one of these URLs:"
+ PrintUrls
+ echo -e "Then, login using the credentials you have created before."
+ echo
+ read -p "Please enter your username here: " USERNAME
+ echo
+ fi
+fi
+
+if ([ ! -f $USERNAME_FILE ] || [ ! -f $TOKEN_FILE ]); then
+ # There is no USERNAME_FILE or TOKEN_FILE, so we ask the user to provide the token.
+ echo
+ echo "If you already have generated a token, and know it, skip this step and just enter it below instead of creating a new one."
+ echo -e "Once you reach the Welcome page, please go to one of these URLs:"
+ PrintUrls "/user/$USERNAME/configure"
+ echo -e "Here you click the \"${GREEN}Add new Token${NOCOLOR}\" button, followed by the \"${GREEN}Generate${NOCOLOR}\" button (leave the text field empty)."
+ echo
+ read -p "Please enter the generated token here, and press enter: " TOKEN
+ echo
+fi
+
+if ([ -f $USERNAME_FILE ] && [ -f $TOKEN_FILE ]); then
+ # If we get here, the files already exists (so the user wouldn't have been asked above)
+ # So we read them instead.
+ USERNAME=`cat $USERNAME_FILE`
+ TOKEN=`cat $TOKEN_FILE`
+fi
+#endregion
+
+# Ensure the Jenkins CLI has been downloaded.
+EnsureJenkinsCli
+
+# Test the connection to make sure Jenkins is ready.
+TestJenkinsConnection $USERNAME $TOKEN
+
+#region Install needed plugins
+# If we make it here, we know the username and token is valid, and Jenkins is running.
+echo "Installing plugins..."
+echo
+
+declare -A plugins
+plugins["docker-plugin"]="Docker"
+plugins["docker-workflow"]="Docker Pipeline"
+plugins["copyartifact"]="Copy Artifact"
+plugins["ssh-agent"]="SSH Agent"
+plugins["pipeline-utility-steps"]="Pipeline Utility Steps"
+plugins["job-dsl"]="Job DSL"
+
+for key in "${!plugins[@]}"
+do
+ if (java -jar jenkins-cli.jar -s http://172.17.17.17:8080 -auth $USERNAME:$TOKEN list-plugins $key > /dev/null 2>&1); then
+ PrintOkIndicator "$key is already installed."
+ else
+ function InstallPlugin {
+ java -jar jenkins-cli.jar -s http://172.17.17.17:8080 -auth $USERNAME:$TOKEN install-plugin $1 -deploy
+ }
+
+ Run "InstallPlugin $key" \
+ "Installing $key plugin..." \
+ "Failed to install $key plugin." \
+ "Installed $key plugin."
+ fi
+done
+
+echo
+#endregion
+
+#region Configure number of executors
+# Find the number of CPU cores available to the machine.
+NUMBER_OF_CPU_CORES="$(nproc)"
+
+# If the number is less than 4, we bump it up to 4.
+NUMBER_OF_CPU_CORES=$(( $NUMBER_OF_CPU_CORES < 4 ? 4 : $NUMBER_OF_CPU_CORES))
+
+# Does the number of exectutors match the number of CPU cores?
+if [ "$(xmlstarlet sel -t -v '//numExecutors' -n /var/lib/jenkins/config.xml 2>/dev/null)" -eq $NUMBER_OF_CPU_CORES ]; then
+ # Yep.
+ PrintOkIndicator "Executors already set to ${NUMBER_OF_CPU_CORES}."
+else
+ # Nope, so we stop Jenkins
+ StopJenkins
+
+ function ChangeExecutorCount {
+ # We need to send 2 to /dev/null, since xmlstarlet prints warnings about xml version to stderr.
+ xmlstarlet ed -L -u "/hudson/numExecutors" -v "$1" $JENKINS_CONFIG_FILE 2>/dev/null
+ }
+
+ # Then we update the config to match the number of CPU cores.
+ Run "ChangeExecutorCount ${NUMBER_OF_CPU_CORES}" \
+ "Changing executor count to ${NUMBER_OF_CPU_CORES}..." \
+ "Failed to change executor count to ${NUMBER_OF_CPU_CORES}." \
+ "Changed executor count to ${NUMBER_OF_CPU_CORES}."
+fi
+#endregion
+
+#region Configure labels
+# Has the labels been configured?
+if grep -q ec2_amd64 $JENKINS_CONFIG_FILE; then
+ # Yep.
+ PrintOkIndicator "Labels are already configured."
+else
+ # Nope, so we stop Jenkins
+ StopJenkins
+
+ function ConfigureLabels {
+ # We need to send 2 to /dev/null, since xmlstarlet prints warnings about xml version to stderr.
+ xmlstarlet ed -L -u "/hudson/label" -v "Docker docker ec2_amd64" $JENKINS_CONFIG_FILE 2>/dev/null
+ }
+
+ # Then we update the config to include the labels.
+ Run "ConfigureLabels" \
+ "Configuring labels..." \
+ "Failed to configure labels." \
+ "Configured labels."
+fi
+#endregion
+
+#region Configure environment variables
+# Does the config contain the environment variables?
+if grep -q ARM64_BUILD_DISABLED $JENKINS_CONFIG_FILE; then
+ # Yep
+ PrintOkIndicator "Environment variables are already configured."
+else
+ # Nope, so we stop Jenkins
+ StopJenkins
+
+ function ConfigureEnvironmentVariables {
+ # We need to send 2 to /dev/null, since xmlstarlet prints warnings about xml version to stderr.
+ xmlstarlet ed -L -s "/hudson/globalNodeProperties" -t elem -n "hudson.slaves.EnvironmentVariablesNodeProperty" -v "" \
+ -s "//hudson.slaves.EnvironmentVariablesNodeProperty" -t elem -n "envVars" -v "" \
+ -s "//envVars" -t attr -n "serialization" -v "custom" \
+ -s "//envVars" -t elem -n "unserializable-parents" -v "" \
+ -s "//envVars" -t elem -n "tree-map" -v "" \
+ -s "//tree-map" -t elem -n "default" -v "" \
+ -s "//default" -t elem -n "comparator" -v "" \
+ -i "//comparator" -t attr -n "class" -v "java.lang.String\$CaseInsensitiveComparator" \
+ -s "//tree-map" -t elem -n "int" -v "4" \
+ -s "//tree-map" -t elem -n "string" -v "ARM64_BUILD_DISABLED" \
+ -s "//tree-map" -t elem -n "string" -v "true" \
+ -s "//tree-map" -t elem -n "string" -v "CUSTOM_BUILD_CHECK_DISABLED" \
+ -s "//tree-map" -t elem -n "string" -v "true" \
+ -s "//tree-map" -t elem -n "string" -v "CUSTOM_DOCKER_REPO" \
+ -s "//tree-map" -t elem -n "string" -v "172.17.17.17:5000" \
+ -s "//tree-map" -t elem -n "string" -v "DEV_PACKAGES_VYOS_NET_HOST" \
+ -s "//tree-map" -t elem -n "string" -v "jenkins@172.17.17.17" \
+ $JENKINS_CONFIG_FILE 2>/dev/null
+ }
+
+ # Then we update the config to include the environment variables.
+ Run "ConfigureEnvironmentVariables" \
+ "Configuring environment variables..." \
+ "Failed to configure environment variables." \
+ "Configured environment variables."
+fi
+#endregion
+
+#region Configure Global Libraries
+# Sometimes the GlobalLibraries config file isn't there yet.
+if [ ! -f $JENKINS_GLOBALLIBRARIES_FILE ]; then
+ # If that is the case, we copy a clean config into where it should be.
+ cp install-files/org.jenkinsci.plugins.workflow.libs.GlobalLibraries.xml $JENKINS_GLOBALLIBRARIES_FILE
+fi
+
+# Is the Global Libraries configured?
+if grep -q "vyos-build" $JENKINS_GLOBALLIBRARIES_FILE; then
+ # Yep.
+ PrintOkIndicator "Global libraries are already configured."
+else
+ # Nope, so we stop Jenkins
+ StopJenkins
+
+ function ConfigureGlobalLibraries {
+ # We need to send 2 to /dev/null, since xmlstarlet prints warnings about xml version to stderr.
+ xmlstarlet ed -L \
+ -d "/org.jenkinsci.plugins.workflow.libs.GlobalLibraries/libraries/@class" \
+ -s "/org.jenkinsci.plugins.workflow.libs.GlobalLibraries/libraries" -t elem -n "org.jenkinsci.plugins.workflow.libs.LibraryConfiguration" -v "" \
+ -s "//org.jenkinsci.plugins.workflow.libs.LibraryConfiguration" -t elem -n "name" -v "vyos-build" \
+ -s "//org.jenkinsci.plugins.workflow.libs.LibraryConfiguration" -t elem -n "retriever" \
+ -i "//retriever" -t attr -n "class" -v "org.jenkinsci.plugins.workflow.libs.SCMSourceRetriever" \
+ -s "//retriever" -t elem -n "clone" -v "false" \
+ -s "//retriever" -t elem -n "scm" \
+ -i "//scm" -t attr -n "class" -v "jenkins.plugins.git.GitSCMSource" \
+ -i "//scm" -t attr -n "plugin" -v "git@5.2.2" \
+ -s "//scm" -t elem -n "id" -v "9d202e32-1889-4391-91e5-1b3445f035fd" \
+ -s "//scm" -t elem -n "remote" -v "https://github.com/dd010101/vyos-build.git" \
+ -s "//scm" -t elem -n "credentialsId" \
+ -s "//scm" -t elem -n "traits" \
+ -s "//traits" -t elem -n "jenkins.plugins.git.traits.BranchDiscoveryTrait" \
+ -s "//org.jenkinsci.plugins.workflow.libs.LibraryConfiguration" -t elem -n "implicit" -v "false" \
+ -s "//org.jenkinsci.plugins.workflow.libs.LibraryConfiguration" -t elem -n "allowVersionOverride" -v "true" \
+ -s "//org.jenkinsci.plugins.workflow.libs.LibraryConfiguration" -t elem -n "includeInChangesets" -v "true" \
+ $JENKINS_GLOBALLIBRARIES_FILE 2>/dev/null
+ }
+
+ # Then we update the config to global libraries configuration.
+ Run "ConfigureGlobalLibraries" \
+ "Configuring global libraries..." \
+ "Failed to configure global libraries." \
+ "Configured global libraries."
+fi
+#endregion
+
+#region Configure Docker Declarative Pipeline
+# Sometimes the Docker Declarative config file isn't there yet.
+if [ ! -f $JENKINS_DOCKERDECLARATIVE_FILE ]; then
+ # If that is the case, we copy a clean config into where it should be.
+ cp install-files/org.jenkinsci.plugins.docker.workflow.declarative.GlobalConfig.xml $JENKINS_DOCKERDECLARATIVE_FILE
+fi
+
+# Is the Docker Declarative plugin configured?
+if grep -q "172.17.17.17" $JENKINS_DOCKERDECLARATIVE_FILE; then
+ # Yep.
+ PrintOkIndicator "Docker Declarativ Pipeline is already configured."
+else
+ # Nope, so we stop Jenkins
+ StopJenkins
+
+ function ConfigureDockerDeclarativePipeline {
+ # We need to send 2 to /dev/null, since xmlstarlet prints warnings about xml version to stderr.
+ xmlstarlet ed -L \
+ -s "/org.jenkinsci.plugins.docker.workflow.declarative.GlobalConfig/registry" -t elem -n "url" -v "http://172.17.17.17:5000" \
+ $JENKINS_DOCKERDECLARATIVE_FILE 2>/dev/null
+ }
+
+ # Then we update the config to global libraries configuration.
+ Run "ConfigureDockerDeclarativePipeline" \
+ "Configuring Docker Declarativ Pipeline..." \
+ "Failed to configure Docker Declarativ Pipeline." \
+ "Configured Docker Declarativ Pipeline."
+fi
+#endregion
+
+# Restart Jenkins if it was stopped.
+StartJenkins
+
+#region Add SSH credentials
+if (java -jar jenkins-cli.jar -s http://172.17.17.17:8080 -auth $USERNAME:$TOKEN get-credentials-as-xml system::system::jenkins _ SSH-dev.packages.vyos.net > /dev/null 2>&1); then
+ PrintOkIndicator "SSH key credential has already been created."
+else
+ function CreateSshKeyCredential {
+ java -jar jenkins-cli.jar -s http://172.17.17.17:8080 -auth $USERNAME:$TOKEN create-credentials-by-xml system::system::jenkins _ << EOF
+<com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey plugin="ssh-credentials@337.v395d2403ccd4">
+ <scope>GLOBAL</scope>
+ <id>SSH-dev.packages.vyos.net</id>
+ <description></description>
+ <username>jenkins</username>
+ <usernameSecret>false</usernameSecret>
+ <privateKeySource class="com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey\$DirectEntryPrivateKeySource">
+ <privateKey>`cat /var/lib/jenkins/.ssh/id_ed25519`</privateKey>
+ </privateKeySource>
+</com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey>
+EOF
+ }
+
+ # We have to create the credential, since it is missing.
+ Run "CreateSshKeyCredential" \
+ "Creating SSH key credential..." \
+ "Failed to create SSH key credential." \
+ "SSH key credential has been created."
+fi
+#endregion
+
+echo
+echo "Part 2 of the installer is now done."
+echo "Please run part three to set up the reprepro repositories."
+
+# Create marker file
+CreateMarkerFile 2 \ No newline at end of file
diff --git a/3-repositories.sh b/3-repositories.sh
new file mode 100755
index 0000000..962efaf
--- /dev/null
+++ b/3-repositories.sh
@@ -0,0 +1,110 @@
+#!/usr/bin/env bash
+
+source ./helper-logic
+
+# Clear the screen and print the header
+PrintHeader
+
+# Ensure we are running as root
+EnsureRoot
+
+# Ensure stage 2 is complete
+EnsureStageIsComplete 2
+
+# Declare variables
+declare -a RELEASES=("equuleus" "sagitta")
+
+#region GnuPG signing key
+# We need to find the public key, since it should be written into the repo config file.
+PrintEmptyIndicator "Getting GnuPG signing key..."
+SIGN_PUB_KEY=`GNUPGHOME="/var/lib/jenkins/.gnupg" gpg --list-secret-keys --keyid-format=long 2>&1 | grep --only-matching --extended-regexp "[[:xdigit:]]{40}"`
+
+if [ ! -z $SIGN_PUB_KEY ]; then
+ ClearPreviousLine
+ PrintOkIndicator "Found GnuPG signing key."
+else
+ ClearPreviousLine
+ PrintErrorIndicator "Failed to find GnuPG signing key."
+fi
+#endregion
+
+#region Repository folders and files
+for release in ${RELEASES[@]}; do
+ REPOSITORY=/home/sentrium/web/dev.packages.vyos.net/public_html/repositories/$release
+
+ if [ -d $REPOSITORY ]; then
+ PrintOkIndicator "Repository for $release already exists."
+ else
+ function CreateRepositoryFolder {
+ mkdir -p $1/conf
+ }
+
+ Run "CreateRepositoryFolder $REPOSITORY" \
+ "Creating repository for release $release..." \
+ "Failed to create folder for release $release." \
+ "Repository for release $release has been created."
+ fi
+
+ if [ -f $REPOSITORY/conf/distributions ]; then
+ PrintOkIndicator "Distributions file for $release already exists."
+ else
+ function CreateDistributionsFile {
+ cat << EOF > $1/conf/distributions
+Origin: $release
+Label: $release
+Codename: $release
+Architectures: source amd64
+Components: main
+Description: $release
+SignWith: $SIGN_PUB_KEY
+EOF
+ }
+
+ Run "CreateDistributionsFile $REPOSITORY" \
+ "Creating distributions file for release $release..." \
+ "Failed to create distributions file for release $release." \
+ "Distributions file for release $release has been created."
+ fi
+
+ if [ -f $REPOSITORY/conf/options ]; then
+ PrintOkIndicator "Options file for $release already exists."
+ else
+ function CreateOptionsFile {
+ cat << EOF > $1/conf/options
+verbose
+EOF
+ }
+
+ Run "CreateOptionsFile $REPOSITORY" \
+ "Creating options file for release $release..." \
+ "Failed to create options file for release $release." \
+ "Options file for release $release has been created."
+ fi
+done
+#endregion
+
+#region Install GnuPG signing public key
+if [ -f /home/sentrium/web/dev.packages.vyos.net/public_html/repositories/apt.gpg.key ]; then
+ PrintOkIndicator "GnuPG key has already been exported."
+else
+ function ExportGnuPGKey {
+ # We need to move 2 to /dev/null to prevent warnings about permissions on the .gnupg folder (they are not important in this case)
+ GNUPGHOME="/var/lib/jenkins/.gnupg" gpg --armor --output /home/sentrium/web/dev.packages.vyos.net/public_html/repositories/apt.gpg.key --export-options export-minimal --export vyos 2>&1
+ }
+
+ Run "ExportGnuPGKey" \
+ "Exporting GnuPG key to file..." \
+ "Failed to export GnuPG key to file." \
+ "GnuPG key has been exported to file."
+fi
+#endregion
+
+# Finally we need to make sure the jenkins user and group owns the sentrium folder and all files in it.
+chown -R jenkins:jenkins /home/sentrium
+
+echo
+echo "Part 3 of the installer is now done."
+echo "Please run part four to set up uncron."
+
+# Create marker file
+CreateMarkerFile 3 \ No newline at end of file
diff --git a/4-uncron.sh b/4-uncron.sh
new file mode 100755
index 0000000..fb3ce00
--- /dev/null
+++ b/4-uncron.sh
@@ -0,0 +1,90 @@
+#!/usr/bin/env bash
+
+source ./helper-logic
+
+# Clear the screen and print the header
+PrintHeader
+
+# Ensure we are running as root
+EnsureRoot
+
+# Ensure stage 3 is complete
+EnsureStageIsComplete 3
+
+#region Run Uncron script
+cp install-files/uncron-script.sh /var/lib/jenkins
+chown jenkins:jenkins /var/lib/jenkins/uncron-script.sh
+
+# This script builds the uncron package.
+echo "Running uncron script as jenkins user..."
+runuser -l jenkins -c "./uncron-script.sh"
+echo
+
+rm /var/lib/jenkins/uncron-script.sh > /dev/null 2>&1
+#endregion
+
+#region Copy uncron into sbin
+if [ -f /usr/local/sbin/uncron ]; then
+ PrintOkIndicator "Uncron has already been installed."
+else
+ function InstallUncron {
+ cp /var/lib/jenkins/uncron/_build/install/default/bin/uncron /usr/local/sbin/
+ }
+
+ Run "InstallUncron" \
+ "Installing Uncron..." \
+ "Failed to install Uncron." \
+ "Uncron has been installed."
+fi
+#endregion
+
+#region Setup systemd service file
+if [ -f /etc/systemd/system/uncron.service ]; then
+ PrintOkIndicator "SystemD service file has already been copied."
+else
+ function CopySystemDServiceFile {
+ cp ./install-files/uncron.service /etc/systemd/system
+ }
+
+ Run "CopySystemDServiceFile" \
+ "Copying SystemD service file..." \
+ "Failed to copy SystemD service file." \
+ "SystemD file has been copied."
+fi
+#endregion
+
+#region Install Uncron Add
+if [ -f /usr/local/bin/uncron-add ]; then
+ PrintOkIndicator "Uncron Add has already been installed."
+else
+ function InstallUncronAdd {
+ cp ./install-files/uncron-add /usr/local/bin
+ chmod +x /usr/local/bin/uncron-add
+ chmod +x /var/lib/jenkins/uncron/src/uncron-add
+ }
+
+ Run "InstallUncronAdd" \
+ "Installing Uncron Add..." \
+ "Failed to install Uncron Add." \
+ "Uncron Add has been installed."
+fi
+#endregion
+
+#region Uncron config
+if [ ! -f /etc/uncron.conf ]; then
+ touch /etc/uncron.conf
+fi
+#endregion
+
+# Reload daemons.
+systemctl daemon-reload > /dev/null 2>&1
+
+# Ensure uncron service is enabled.
+systemctl enable --now uncron.service > /dev/null 2>&1
+
+echo
+echo "Part 4 of the installer is now done."
+echo "Please run part five to set up the vyos build container jobs."
+
+# Create marker file
+CreateMarkerFile 4 \ No newline at end of file
diff --git a/5-docker-jobs.sh b/5-docker-jobs.sh
new file mode 100755
index 0000000..b9cd376
--- /dev/null
+++ b/5-docker-jobs.sh
@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+
+source ./helper-logic
+
+# Clear the screen and print the header
+PrintHeader
+
+# Ensure we are running as root
+EnsureRoot
+
+# Ensure stage 4 is complete
+EnsureStageIsComplete 4
+
+# If the username and token has been saved, we use those instead of asking the user.
+if ([ ! -f $USERNAME_FILE ] || [ ! -f $TOKEN_FILE ]); then
+ echo
+ read -p "Please enter your username here: " USERNAME
+ read -p "Please enter your Jenkins token here: " TOKEN
+ echo
+else
+ USERNAME=`cat $USERNAME_FILE`
+ TOKEN=`cat $TOKEN_FILE`
+fi
+
+# Define the JENKINS url using the username and token provided.
+JENKINS_URL="http://${USERNAME}:${TOKEN}@172.17.17.17:8080"
+
+# Ensure the Jenkins CLI has been downloaded.
+EnsureJenkinsCli
+
+# Test the connection to make sure Jenkins is ready.
+TestJenkinsConnection $USERNAME $TOKEN
+
+echo
+
+# Provision the jobs.
+ProvisionJobs "jobs/docker-container-jobs.json"
+
+echo
+
+# Build the jobs.
+BuildJobs "jobs/docker-container-jobs.json"
+
+if [ $? -eq 0 ]; then
+ echo
+ echo "Containers has been built."
+ echo "Part 5 of the installer is now done."
+ echo "Please run part six to set up the project jobs."
+ echo
+else
+ echo
+ echo "One or more container failed to build."
+ echo "Please check inside Jenkins to see what went wrong, and run a new build of the failed container."
+ echo "Once this is done, please run part six to set up the project job."
+ echo
+fi
+
+# Create marker file
+CreateMarkerFile 5 \ No newline at end of file
diff --git a/6-provision-project-jobs.sh b/6-provision-project-jobs.sh
new file mode 100755
index 0000000..8b89cd8
--- /dev/null
+++ b/6-provision-project-jobs.sh
@@ -0,0 +1,45 @@
+#!/usr/bin/env bash
+
+source ./helper-logic
+
+# Clear the screen and print the header
+PrintHeader
+
+# Ensure we are running as root
+EnsureRoot
+
+# Ensure stage 5 is complete
+EnsureStageIsComplete 5
+
+# If the username and token has been saved, we use those instead of asking the user.
+if ([ ! -f $USERNAME_FILE ] || [ ! -f $TOKEN_FILE ]); then
+ echo
+ read -p "Please enter your username here: " USERNAME
+ read -p "Please enter your Jenkins token here: " TOKEN
+ echo
+else
+ USERNAME=`cat $USERNAME_FILE`
+ TOKEN=`cat $TOKEN_FILE`
+fi
+
+# Define the JENKINS url using the username and token provided.
+JENKINS_URL="http://${USERNAME}:${TOKEN}@172.17.17.17:8080"
+
+# Ensure the Jenkins CLI has been downloaded.
+EnsureJenkinsCli
+
+# Test the connection to make sure Jenkins is ready.
+TestJenkinsConnection $USERNAME $TOKEN
+
+echo
+
+# Provision the jobs.
+ProvisionJobs "jobs/project-jobs.json"
+
+echo
+echo "The project jobs has been provisioned."
+echo "Part 6 of the installer is now done."
+echo "Please run part seven to build the project jobs."
+
+# Create marker file
+CreateMarkerFile 6 \ No newline at end of file
diff --git a/7-build-project-jobs.sh b/7-build-project-jobs.sh
new file mode 100755
index 0000000..7623f12
--- /dev/null
+++ b/7-build-project-jobs.sh
@@ -0,0 +1,55 @@
+#!/usr/bin/env bash
+
+source ./helper-logic
+
+# Clear the screen and print the header
+PrintHeader
+
+# Ensure we are running as root
+EnsureRoot
+
+# Ensure stage 6 is complete
+EnsureStageIsComplete 6
+
+# If the username and token has been saved, we use those instead of asking the user.
+if ([ ! -f $USERNAME_FILE ] || [ ! -f $TOKEN_FILE ]); then
+ echo
+ read -p "Please enter your username here: " USERNAME
+ read -p "Please enter your Jenkins token here: " TOKEN
+ echo
+else
+ USERNAME=`cat $USERNAME_FILE`
+ TOKEN=`cat $TOKEN_FILE`
+fi
+
+# Define the JENKINS url using the username and token provided.
+JENKINS_URL="http://${USERNAME}:${TOKEN}@172.17.17.17:8080"
+
+# Ensure the Jenkins CLI has been downloaded.
+EnsureJenkinsCli
+
+# Test the connection to make sure Jenkins is ready.
+TestJenkinsConnection $USERNAME $TOKEN
+
+echo
+
+# Build the jobs.
+BuildJobs "jobs/project-jobs.json"
+
+if [ $? -eq 0 ]; then
+ echo
+ echo "All packages have been built."
+ echo "Part 7 of the installer is now done."
+ echo "Please run part eight to set up NGINX."
+ echo
+else
+ echo
+ echo "One or more packages failed to build."
+ echo "A list of failed jobs is printed above."
+ echo "Please check inside Jenkins to see what went wrong, and run a new build of the failed package."
+ echo "Once this is done, please run part eight to set up NGINX."
+ echo
+fi
+
+# Create marker file
+CreateMarkerFile 7 \ No newline at end of file
diff --git a/8-nginx.sh b/8-nginx.sh
new file mode 100755
index 0000000..97125d4
--- /dev/null
+++ b/8-nginx.sh
@@ -0,0 +1,81 @@
+#!/usr/bin/env bash
+
+source ./helper-logic
+
+# Clear the screen and print the header
+PrintHeader
+
+# Ensure we are running as root
+EnsureRoot
+
+# Ensure stage 7 is complete
+EnsureStageIsComplete 7
+
+# Add NGINX configuration
+echo "Configuring NGINX..."
+
+#region NGINX default configuration
+if [ -f /etc/nginx/sites-enabled/default ]; then
+ function RemoveDefaultNginxConfiguration() {
+ rm /etc/nginx/sites-enabled/default
+ }
+
+ Run "RemoveDefaultNginxConfiguration" \
+ "Removing default NGINX configuration..." \
+ "Failed to remove default NGINX configuration." \
+ "Default NGINX configuration has been removed."
+fi
+#endregion
+
+#region NGINX apt-mirror configuration
+if [ -f /etc/nginx/sites-available/apt-mirror ]; then
+ function RemoveAptMirrorNginxConfiguration() {
+ rm /etc/nginx/sites-available/apt-mirror
+ }
+
+ Run "RemoveAptMirrorNginxConfiguration" \
+ "Removing apt-mirror NGINX configuration..." \
+ "Failed to remove apt-mirror NGINX configuration." \
+ "Apt-mirror NGINX configuration has been removed."
+fi
+
+function CopyAvailableSiteFile {
+ cp install-files/nginx-site /etc/nginx/sites-available/apt-mirror
+}
+
+Run "CopyAvailableSiteFile" \
+ "Copying apt-mirror NGINX configuration file..." \
+ "Failed to copy apt-mirror NGINX configuration." \
+ "Apt-mirror NGINX configuration has been copied."
+#endregion
+
+#region Enable NGINX apt-mirror configuration
+if [ ! -f /etc/nginx/sites-enabled/apt-mirror ]; then
+ function LinkAptMirrorNginxConfiguration() {
+ ln -s /etc/nginx/sites-available/apt-mirror /etc/nginx/sites-enabled/apt-mirror
+ }
+
+ Run "LinkAptMirrorNginxConfiguration" \
+ "Linking apt-mirror NGINX configuration file..." \
+ "Failed to link apt-mirror NGINX configuration." \
+ "Apt-mirror NGINX configuration has been linked."
+fi
+#endregion
+
+#region Restart NGINX
+function RestartNginx() {
+ systemctl restart nginx
+}
+
+Run "RestartNginx" \
+ "Restarting NGINX..." \
+ "Failed to restart NGINX." \
+ "NGINX has been restarted."
+#endregion
+
+echo
+echo "Part 8 of the installer is now done."
+echo "The installation is now done - you can build the ISO by running the build-iso bash script."
+
+# Create marker file
+CreateMarkerFile 8 \ No newline at end of file
diff --git a/helper-logic b/helper-logic
new file mode 100644
index 0000000..a1f6c17
--- /dev/null
+++ b/helper-logic
@@ -0,0 +1,584 @@
+#!/usr/bin/env bash
+
+# Define colors.
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+LIGHTBLUE='\033[0;94m'
+NOCOLOR='\033[0m'
+
+# Define color indicators.
+EMPTY_INDICATOR="[ ]"
+OK_INDICATOR="[ ${GREEN}OK${NOCOLOR} ]"
+ERROR_INDICATOR="[ ${RED}!!${NOCOLOR} ]"
+
+# Define job indicators.
+JOB_NOT_STARTED_INDICATOR="[ ${LIGHTBLUE}Not Started${NOCOLOR} ]"
+JOB_RUNNING_INDICATOR="[ ${LIGHTBLUE}Running${NOCOLOR} ]"
+JOB_COMPLETED_INDICATOR="[ ${GREEN}Completed${NOCOLOR} ]"
+JOB_FAILED_INDICATOR="[ ${RED}Failed!${NOCOLOR} ]"
+
+# Define username and token filenames.
+USERNAME_FILE=/tmp/installer_username
+TOKEN_FILE=/tmp/installer_token
+
+# Define Jenkins config files.
+JENKINS_CONFIG_FILE=/var/lib/jenkins/config.xml
+JENKINS_GLOBALLIBRARIES_FILE=/var/lib/jenkins/org.jenkinsci.plugins.workflow.libs.GlobalLibraries.xml
+JENKINS_DOCKERDECLARATIVE_FILE=/var/lib/jenkins/org.jenkinsci.plugins.docker.workflow.declarative.GlobalConfig.xml
+
+# Define the job template variables.
+TEMPLATE_FILE="jobs/jobTemplate.xml"
+WORKDIR="/tmp/seed-jobs"
+
+function PrintHeader {
+ # Clear the screen first
+ clear
+
+ # Print banner
+ echo "#################################################"
+ echo "# Unofficial VyOS package mirror installer v1.0 #"
+ echo "#################################################"
+ echo
+}
+
+function EnsureRoot {
+ # Ensure we are root
+ if [ "$EUID" -ne 0 ]; then
+ echo -e "${RED}Please run as root${NOCOLOR}"
+ exit
+ fi
+}
+
+function ClearPreviousLine {
+ tput cuu1
+ tput el
+}
+
+function PrintEmptyIndicator {
+ echo -e "$EMPTY_INDICATOR $1"
+}
+
+function PrintOkIndicator {
+ echo -e "$OK_INDICATOR $1"
+}
+
+function PrintErrorIndicator {
+ echo -e "$ERROR_INDICATOR $1"
+ exit
+}
+
+function PrintJobNotStarted {
+ tput el
+ echo -e "[ ${LIGHTBLUE}Not Started${NOCOLOR} ] Package: $1 - Branch: $2"
+}
+
+function PrintJobRunning {
+ tput el
+ echo -e "[ ${LIGHTBLUE}Running${NOCOLOR} ] Package: $1 - Branch: $2"
+}
+
+function PrintJobCompleted {
+ tput el
+ echo -e "[ ${GREEN}Completed${NOCOLOR} ] Package: $1 - Branch: $2"
+}
+
+function PrintJobFailed {
+ tput el
+ echo -e "[ ${RED}Failed!${NOCOLOR} ] Package: $1 - Branch: $2"
+}
+
+function Run {
+ command="$1"
+ infoMessage="$2"
+ errorMessage="$3"
+ successMessage="$4"
+
+ if [ "$infoMessage" != "" ]; then
+ echo -e "$EMPTY_INDICATOR $infoMessage"
+ fi
+
+ output=$( (set -e; eval "$command") 2>&1 1>/dev/null | tee /dev/fd/2; exit ${PIPESTATUS[0]} )
+ exitCode=$?
+
+ if [ $exitCode -eq 0 ]; then
+ if [ "$successMessage" != "" ]; then
+ if [ "$output" == "" ]; then
+ tput cuu1; tput el
+ fi
+ echo -e "$OK_INDICATOR $successMessage"
+ fi
+ else
+ if [ "$output" == "" ]; then
+ tput cuu1; tput el
+ fi
+ if [ "$successMessage" != "" ]; then
+ >&2 echo -e "$ERROR_INDICATOR $errorMessage"
+ else
+ >&2 echo -e "$ERROR_INDICATOR Unexpected failure, exit code: $exitCode"
+ fi
+ exit $exitCode
+ fi
+}
+
+function EnsureJenkinsCli {
+ if [ ! -f jenkins-cli.jar ]; then
+ PrintEmptyIndicator "Download Jenkins CLI..."
+ wget http://172.17.17.17:8080/jnlpJars/jenkins-cli.jar > /dev/null 2>&1
+
+ if [ $? -eq 0 ]; then
+ ClearPreviousLine
+ PrintOkIndicator "Downloaded Jenkins CLI successfully."
+ else
+ ClearPreviousLine
+ PrintErrorIndicator "Failed to download Jenkins CLI."
+ fi
+ fi
+}
+
+function TestJenkinsConnection {
+ PrintEmptyIndicator "Testing jenkins connection..."
+ java -jar jenkins-cli.jar -s http://172.17.17.17:8080 -auth $1:$2 > /dev/null 2>&1
+
+ if [ $? -eq 0 ]; then
+ ClearPreviousLine
+ PrintOkIndicator "Connected to Jenkins successfully."
+
+ echo $1 > $USERNAME_FILE
+ echo $2 > $TOKEN_FILE
+ else
+ ClearPreviousLine
+ PrintErrorIndicator "Failed to connect to Jenkins, please re-run stage 2 and make sure the username and token is correct."
+ echo
+
+ if [ -f $USERNAME_FILE ]; then
+ rm $USERNAME_FILE
+ fi
+
+ if [ -f $TOKEN_FILE ]; then
+ rm $TOKEN_FILE
+ fi
+
+ exit
+ fi
+}
+
+function StopJenkins {
+ if [ $(systemctl is-active jenkins) == "active" ]; then
+ PrintEmptyIndicator "Stopping Jenkins..."
+ service jenkins stop > /dev/null 2>&1
+
+ if [ $? -eq 0 ]; then
+ ClearPreviousLine
+ PrintOkIndicator "Jenkins has been stopped."
+ else
+ ClearPreviousLine
+ PrintErrorIndicator "Failed to stop Jenkins."
+ fi
+ fi
+}
+
+function StartJenkins {
+ if [ $(systemctl is-active jenkins) != "active" ]; then
+ PrintEmptyIndicator "Starting Jenkins..."
+ service jenkins start > /dev/null 2>&1
+
+ if [ $? -eq 0 ]; then
+ ClearPreviousLine
+ PrintOkIndicator "Jenkins has been started."
+ else
+ ClearPreviousLine
+ PrintErrorIndicator "Failed to start Jenkins."
+ fi
+ fi
+}
+
+function UrlGet {
+ curl -sS -g --fail-with-body "${JENKINS_URL}${1}"
+}
+
+function UrlPost {
+ curl -sS -g --fail-with-body -X POST "${JENKINS_URL}${1}"
+}
+
+function UrlPush {
+ curl -sS -g --fail-with-body -X POST -d "@${2}" -H "Content-Type: text/xml" "${JENKINS_URL}${1}"
+}
+
+function ProvisionJob {
+ # Extract the job name.
+ JOB_NAME=$(echo "$1" | jq -r .name)
+
+ # Print the job name.
+ PrintEmptyIndicator "$JOB_NAME"
+
+ # Parse the json.
+ DESCRIPTION=$(echo "$1" | jq -r .description)
+ GIT_URL=$(echo "$1" | jq -r .gitUrl)
+ BRANCH_REGEX=$(echo "$1" | jq -r .branchRegex)
+ JENKINS_FILE_PATH=$(echo "$1" | jq -r .jenkinsfilePath)
+
+ # Create the job xml file.
+ JOBPATH="$WORKDIR/$JOB_NAME.xml"
+ PROJECT="org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject"
+ BRANCH_SOURCE="$PROJECT/sources/data/jenkins.branch.BranchSource/source"
+ REGEX_TRAIT="$BRANCH_SOURCE/traits/jenkins.scm.impl.trait.RegexSCMHeadFilterTrait"
+ xmlstarlet ed --update "//$PROJECT/description" --value "$DESCRIPTION" \
+ --update "//$BRANCH_SOURCE/remote" --value "$GIT_URL" \
+ --update "//$REGEX_TRAIT/regex" --value "$BRANCH_REGEX" \
+ --update "//$PROJECT/factory/scriptPath" --value "$JENKINS_FILE_PATH" \
+ "$TEMPLATE_FILE" > "$JOBPATH" 2>/dev/null
+
+ if [ $? -ne 0 ]; then
+ ClearPreviousLine
+ PrintErrorIndicator "Failed to create job xml for: $JOB_NAME"
+ fi
+
+ # Check if job already exists.
+ RESULT=$(UrlGet "/checkJobName?value=$JOB_NAME" || true)
+
+ if [[ "$RESULT" == *"already exists"* ]]; then
+ # Job already exist, so we update it.
+ UrlPush "/job/$JOB_NAME/config.xml" "$JOBPATH"
+ else
+ # Job doesn't exist, so we create it.
+ UrlPush "/createItem?name=$JOB_NAME" "$JOBPATH"
+ fi
+
+ if [ $? -eq 0 ]; then
+ ClearPreviousLine
+ PrintOkIndicator "$JOB_NAME"
+ else
+ ClearPreviousLine
+ PrintErrorIndicator "Failed to create job: $JOB_NAME"
+ fi
+}
+
+function ProvisionJobs {
+ # Create the jobs.
+ echo "Provisioning jobs in Jenkins..."
+
+ # Declare the JOBS list.
+ declare -a JOBS
+
+ # Make sure the work directory exists.
+ mkdir -p "$WORKDIR"
+
+ # Read one job at a time from the json file.
+ while read item
+ do
+ # Find the name of the job.
+ JOB_NAME=$(echo "$item" | jq -r .name)
+
+ # Find the branches for the job.
+ BRANCH_REGEX=$(echo "$item" | jq -r .branchRegex)
+
+ # Split branch regex
+ BRANCHES=$(sed -e 's/(//g' -e 's/)//g' -e 's/|/\n/g' <<< "${BRANCH_REGEX}")
+
+ for BRANCH in $BRANCHES
+ do
+ JOBS+=( "$JOB_NAME|$BRANCH" )
+ done
+
+ # Provision the job.
+ ProvisionJob $item
+ done < <(cat $1 | jq -c '.[]')
+
+ echo
+ echo "Waiting for jobs to be provisioned in Jenkins..."
+ echo
+ echo "Total number of jobs: ${#JOBS[@]}"
+ echo
+
+ for job in "${JOBS[@]}"; do
+ jobSplit=(${job//|/ })
+ JOB_NAME="${jobSplit[0]}"
+ JOB_BRANCH="${jobSplit[1]}"
+
+ PrintJobNotStarted $JOB_NAME $JOB_BRANCH
+ done
+
+ while :
+ do
+ # Define the current state, and set it to true.
+ # If anything isn't ready, we set it to false.
+ FINISHED_THIS_RUN="true"
+
+ # Move the cursor up to the top of the list on screen.
+ for job in "${JOBS[@]}"; do
+ tput cuu1
+ done
+
+ # Check the status for each job
+ for job in "${JOBS[@]}"; do
+ jobSplit=(${job//|/ })
+ JOB_NAME="${jobSplit[0]}"
+ JOB_BRANCH="${jobSplit[1]}"
+
+ URL="${JENKINS_URL}/job/${JOB_NAME}/job/${JOB_BRANCH}/1/api/json"
+
+ if [ "$(curl -o /dev/null -s -w "%{http_code}\n" "${URL}")" -eq 404 ]; then
+ # The indexing hasn't started for this branch yet.
+ PrintJobNotStarted $JOB_NAME $JOB_BRANCH
+ FINISHED_THIS_RUN="false"
+ else
+ # Indexing has started.
+ RESULT=$(curl -Ss -g --fail-with-body "$URL" | jq -r .result)
+ if [[ "${RESULT}" != "SUCCESS" ]]; then
+ # But it hasn't finished yet.
+ PrintJobRunning $JOB_NAME $JOB_BRANCH
+ FINISHED_THIS_RUN="false"
+ else
+ PrintJobCompleted $JOB_NAME $JOB_BRANCH
+ fi
+ fi
+ done
+
+ # When we get here, if FINISHED_THIS_RUN is true, everything is ready
+ if [[ $FINISHED_THIS_RUN == "true" ]]; then
+ break;
+ else
+ # Sleep 5 seconds
+ sleep 5
+ fi
+ done
+}
+
+function BuildJobs {
+ # Build the jobs.
+ echo "Building jobs in Jenkins..."
+
+ # Declare the JOBS list.
+ declare -a JOBS
+
+ # Read one job at a time from the json file.
+ # Store the single jobs in the JOBS array.
+ while read item
+ do
+ # Find the name of the job.
+ JOB_NAME=$(echo "$item" | jq -r .name)
+
+ # Find the branches for the job.
+ BRANCH_REGEX=$(echo "$item" | jq -r .branchRegex)
+
+ # Split branch regex
+ BRANCHES=$(sed -e 's/(//g' -e 's/)//g' -e 's/|/\n/g' <<< "${BRANCH_REGEX}")
+
+ for BRANCH in $BRANCHES
+ do
+ JOBS+=( "$JOB_NAME|$BRANCH" )
+ done
+ done < <(cat $1 | jq -c '.[]')
+
+ BUILD_FAILED="false"
+
+ echo "Total number of jobs: ${#JOBS[@]}"
+
+ # Has the CONCURRENT_JOBS_COUNT environment variable been set?
+ if [ "$(printenv CONCURRENT_JOBS_COUNT)" ]; then
+ # Yes, so we use that value to define the number of concurrent jobs.
+ CONCURRENT_JOBS_COUNT=$(printenv CONCURRENT_JOBS_COUNT)
+ echo "Concurrent jobs: $CONCURRENT_JOBS_COUNT (Overridden by the CONCURRENT_JOBS_COUNT environment variable)"
+ else
+ # No, so we read the number of CPU cores, and use that.
+ CONCURRENT_JOBS_COUNT="$(nproc)"
+
+ # If less than 4 CPU cores is found, we set it to 4.
+ CONCURRENT_JOBS_COUNT=$(( $CONCURRENT_JOBS_COUNT < 4 ? 4 : $CONCURRENT_JOBS_COUNT))
+ echo "Concurrent jobs: $CONCURRENT_JOBS_COUNT (Can be overridden by setting the CONCURRENT_JOBS_COUNT environment variable)"
+ fi
+
+ echo
+
+ declare -A JOB_RESULTS
+
+ # While there are more jobs to build.
+ while [ ${#JOBS[@]} -gt 0 ]
+ do
+ # Create a list to store the current "chunk" of jobs in.
+ declare -a CURRENT_JOBS
+
+ # Make sure it is empty.
+ CURRENT_JOBS=()
+
+ # While the number of jobs in the list is less than the concurrent job count.
+ while [ ${#CURRENT_JOBS[@]} -lt $CONCURRENT_JOBS_COUNT ]
+ do
+ # Are there any jobs left in the main list?
+ if [ ${#JOBS[@]} -gt 0 ]; then
+ # Yes, so we take the first element.
+ ELEMENT=${JOBS[0]}
+
+ # Remove it from the main list.
+ JOBS=("${JOBS[@]:1}")
+
+ # And add it to our current list.
+ CURRENT_JOBS+=( "$ELEMENT" )
+ else
+ # No more jobs, so we break out of the loop.
+ break
+ fi
+ done
+
+ # For each jobs in the current list.
+ for job in "${CURRENT_JOBS[@]}"; do
+ # Split into name and branch.
+ jobSplit=(${job//|/ })
+ JOB_NAME="${jobSplit[0]}"
+ JOB_BRANCH="${jobSplit[1]}"
+
+ # Download job data and parse it.
+ URL="${JENKINS_URL}/job/${JOB_NAME}/job/${JOB_BRANCH}/lastBuild/api/json"
+ DATA=$(curl -Ss -g --fail-with-body "$URL")
+ NUMBER="$(echo $DATA | jq -r .number)"
+ INPROGRESS="$(echo $DATA | jq -r .inProgress)"
+ RESULT="$(echo $DATA | jq -r .result)"
+
+ # Get the branch build parameters.
+ JSON=`cat $1 | jq --arg jobName "$JOB_NAME" --arg branch "$JOB_BRANCH" '.[] | select(.name == $jobName) | .branchParameters[$branch]'`
+
+ # Build command line.
+ COMMAND="java -jar jenkins-cli.jar -s http://172.17.17.17:8080 -auth $USERNAME:$TOKEN build '$JOB_NAME/$JOB_BRANCH'"
+
+ # Construct the command line with the parameters.
+ if [[ $JSON != "null" ]]; then
+ while read variable
+ do
+ name=$(echo "$variable" | jq -r .key)
+ value=$(echo "$variable" | jq -r .value)
+
+ COMMAND="$COMMAND -p $name=$value"
+ done < <(echo "$JSON" | jq -c 'to_entries | .[]')
+ fi
+
+ # Is the latest job #1 (the branch indexing job)?
+ if [[ "${NUMBER}" == "1" ]]; then
+ # Yes, so we trigger a new build.
+ eval $COMMAND || true
+ # No, so if inProgress is not true, the result is not success and the result is not null.
+ elif [[ "${INPROGRESS}" != "true" ]] && [[ "${RESULT}" != "SUCCESS" ]] && [[ "${RESULT}" != "null" ]]; then
+ # We trigger a new build, since the last build is not running, but didn't succeed.
+ eval $COMMAND || true
+
+ # We need to store the build number we found in a variable.
+ LAST_BUILD_NUMBER=$NUMBER
+
+ # Keep downloading the info for the last build, until the build number doesn't match the one stored above.
+ while :
+ do
+ URL="${JENKINS_URL}/job/${JOB_NAME}/job/${JOB_BRANCH}/lastBuild/api/json"
+ DATA=$(curl -Ss -g --fail-with-body "$URL")
+ NUMBER="$(echo $DATA | jq -r .number)"
+
+ # When that happens, the new build has been started, and we can move on.
+ if [[ "${NUMBER}" != "$LAST_BUILD_NUMBER" ]]; then
+ break
+ fi
+
+ # If not yet, we sleep 5 seconds and try again.
+ sleep 5
+ done
+ fi
+
+ # Once we get to here, we have asked Jenkins to start the job, so we create an initial status of "Not Started".
+ echo -e "[ ${LIGHTBLUE}Not Started${NOCOLOR} ] Package: $JOB_NAME - Branch: $JOB_BRANCH"
+ done
+
+ while :
+ do
+ # Define the current state, and set it to true.
+ # If anything isn't ready, we set it to false.
+ FINISHED_THIS_RUN="true"
+
+ # Move the cursor up one line for each job in the current job list.
+ for job in "${CURRENT_JOBS[@]}"; do
+ tput cuu1
+ done
+
+ # For each job in the current job list.
+ for job in "${CURRENT_JOBS[@]}"; do
+ # Split into name and branch.
+ jobSplit=(${job//|/ })
+ JOB_NAME="${jobSplit[0]}"
+ JOB_BRANCH="${jobSplit[1]}"
+
+ # Download job data and parse it.
+ URL="${JENKINS_URL}/job/${JOB_NAME}/job/${JOB_BRANCH}/lastBuild/api/json"
+ DATA=$(curl -Ss -g --fail-with-body "$URL")
+ NUMBER="$(echo $DATA | jq -r .number)"
+ INPROGRESS="$(echo $DATA | jq -r .inProgress)"
+ RESULT="$(echo $DATA | jq -r .result)"
+
+ if [[ "${NUMBER}" == "1" ]]; then
+ # Job number is 1, so we have the branching indexing job.
+ PrintJobNotStarted $JOB_NAME $JOB_BRANCH
+ FINISHED_THIS_RUN="false"
+ else
+ if [[ "${INPROGRESS}" == "true" ]]; then
+ # inProgress is true, so the job is running.
+ PrintJobRunning $JOB_NAME $JOB_BRANCH
+ FINISHED_THIS_RUN="false"
+ else
+ if [[ "${RESULT}" == "SUCCESS" ]]; then
+ # result is SUCCESS, so the job is done.
+ PrintJobCompleted $JOB_NAME $JOB_BRANCH
+ JOB_RESULTS[$job]="OK"
+ else
+ if [[ "${RESULT}" == "null" ]]; then
+ # result is null, which means we can download the data for the job, but it hasn't started yet.
+ PrintJobNotStarted $JOB_NAME $JOB_BRANCH
+ FINISHED_THIS_RUN="false"
+ else
+ # If we end up here, the job has failed.
+ PrintJobFailed $JOB_NAME $JOB_BRANCH
+ JOB_RESULTS[$job]="FAILED"
+ BUILD_FAILED="true"
+ fi
+ fi
+ fi
+ fi
+ done
+
+ # When we get here, if FINISHED_THIS_RUN is true, everything is ready
+ if [[ $FINISHED_THIS_RUN == "true" ]]; then
+ break;
+ else
+ # Sleep 5 seconds
+ sleep 5
+ fi
+ done
+ done
+
+ if [[ $BUILD_FAILED == "false" ]]; then
+ # All builds succeeded.
+ return 0
+ else
+ # One or more builds failed.
+ # Print the name of those who failed.
+ echo
+ echo "List of failed jobs:"
+ for job in "${!JOB_RESULTS[@]}"
+ do
+ jobSplit=(${job//|/ })
+ JOB_NAME="${jobSplit[0]}"
+ JOB_BRANCH="${jobSplit[1]}"
+
+ if [[ ${JOB_RESULTS[$job]} == "FAILED" ]]; then
+ echo -e "[ ${RED}Failed!${NOCOLOR} ] Package: $JOB_NAME - Branch: $JOB_BRANCH"
+ fi
+ done
+
+ return 1
+ fi
+}
+
+function CreateMarkerFile {
+ touch "/tmp/installer_stage_${1}_completed"
+}
+
+function EnsureStageIsComplete {
+ if [ ! -f "/tmp/installer_stage_${1}_completed" ]; then
+ echo -e "${RED}Stage ${1} has not been completed - please run that first.${NOCOLOR}"
+ exit
+ fi
+} \ No newline at end of file
diff --git a/install-files/daemon.json b/install-files/daemon.json
new file mode 100644
index 0000000..f71dd61
--- /dev/null
+++ b/install-files/daemon.json
@@ -0,0 +1,5 @@
+{
+ "insecure-registries": [
+ "172.17.17.17:5000"
+ ]
+}
diff --git a/install-files/dummy0.interface b/install-files/dummy0.interface
new file mode 100644
index 0000000..a45fcf8
--- /dev/null
+++ b/install-files/dummy0.interface
@@ -0,0 +1,4 @@
+auto dummy0
+iface dummy0 inet static
+ address 172.17.17.17/32
+ pre-up ip link add dummy0 type dummy
diff --git a/install-files/gpg-script.sh b/install-files/gpg-script.sh
new file mode 100755
index 0000000..2e26668
--- /dev/null
+++ b/install-files/gpg-script.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+set -e
+
+# Ensure we are jenkins user
+if [ "$EUID" -ne 1006 ]
+ then echo "Please run as jenkins"
+ exit
+fi
+
+if [ -f ~/.gnupg/pubring.kbx ]; then
+ echo "GnuPG Keypair has already been generated."
+else
+ echo "Generating GnuPG keypair..."
+ gpg --batch --gen-key > /dev/null 2>&1 <<EOF
+ %no-protection
+ Key-Type:1
+ Key-Length:3072
+ Subkey-Type:1
+ Subkey-Length:3072
+ Name-Real: VyOS Unofficial Signing Key
+ Name-Email: signing@not-vyos.org
+ Expire-Date:0
+EOF
+fi
diff --git a/install-files/nginx-site b/install-files/nginx-site
new file mode 100644
index 0000000..56550e5
--- /dev/null
+++ b/install-files/nginx-site
@@ -0,0 +1,21 @@
+server {
+ listen 80;
+ listen [::]:80;
+
+ root /home/sentrium/web/dev.packages.vyos.net/public_html/repositories;
+ autoindex on;
+
+ server_name _;
+
+ location / {
+ try_files $uri $uri/ =404;
+ }
+
+ location ~ /(.*)/conf {
+ deny all;
+ }
+
+ location ~ /(.*)/db {
+ deny all;
+ }
+} \ No newline at end of file
diff --git a/install-files/org.jenkinsci.plugins.docker.workflow.declarative.GlobalConfig.xml b/install-files/org.jenkinsci.plugins.docker.workflow.declarative.GlobalConfig.xml
new file mode 100644
index 0000000..40faa75
--- /dev/null
+++ b/install-files/org.jenkinsci.plugins.docker.workflow.declarative.GlobalConfig.xml
@@ -0,0 +1,5 @@
+<?xml version='1.1' encoding='UTF-8'?>
+<org.jenkinsci.plugins.docker.workflow.declarative.GlobalConfig plugin="docker-workflow@580.vc0c340686b_54">
+ <dockerLabel></dockerLabel>
+ <registry plugin="docker-commons@439.va_3cb_0a_6a_fb_29"/>
+</org.jenkinsci.plugins.docker.workflow.declarative.GlobalConfig> \ No newline at end of file
diff --git a/install-files/org.jenkinsci.plugins.workflow.libs.GlobalLibraries.xml b/install-files/org.jenkinsci.plugins.workflow.libs.GlobalLibraries.xml
new file mode 100644
index 0000000..859b10e
--- /dev/null
+++ b/install-files/org.jenkinsci.plugins.workflow.libs.GlobalLibraries.xml
@@ -0,0 +1,4 @@
+<?xml version='1.1' encoding='UTF-8'?>
+<org.jenkinsci.plugins.workflow.libs.GlobalLibraries plugin="pipeline-groovy-lib@710.v4b_94b_077a_808">
+ <libraries class="empty-list"/>
+</org.jenkinsci.plugins.workflow.libs.GlobalLibraries> \ No newline at end of file
diff --git a/install-files/ssh-script.sh b/install-files/ssh-script.sh
new file mode 100755
index 0000000..abdf7ae
--- /dev/null
+++ b/install-files/ssh-script.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+set -e
+
+# Ensure we are jenkins user
+if [ "$EUID" -ne 1006 ]
+ then echo "Please run as jenkins"
+ exit
+fi
+
+if [ -f ~/.ssh/id_ed25519.pub ]; then
+ echo "SSH keypair has already been generated."
+else
+ echo "Generating SSH keypair..."
+ ssh-keygen -t ed25519 -C "jenkins" -N "" -f /var/lib/jenkins/.ssh/id_ed25519 > /dev/null 2>&1
+fi
+
+if [ -f ~/.ssh/authorized_keys ]; then
+ echo "SSH key has already been authorized."
+else
+ echo "Authorizing SSH key..."
+ cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
+fi
+
+echo "Ensuring SSH host key is trusted..."
+ssh -oStrictHostKeyChecking=no 172.17.17.17 "pwd > /dev/null 2>&1" > /dev/null 2>&1
diff --git a/install-files/uncron-add b/install-files/uncron-add
new file mode 100755
index 0000000..298fd3c
--- /dev/null
+++ b/install-files/uncron-add
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+set -e
+
+COMMAND="$1"
+
+# this is hack to workaround a issue where vyos didn't create sagitta branch
+# like the case of vyos-xe-guest-utilities, thus we need to build current
+# branch and then redirect from here to sagitta repository
+if [ ! -L ~/VyOS/current ]; then
+ rm -rf ~/VyOS/current
+ mkdir -p ~/VyOS/sagitta
+ ln -s ~/VyOS/sagitta ~/VyOS/current
+fi
+if [[ "$COMMAND" == *"repositories/current"* ]]; then
+ COMMAND=${COMMAND//current/sagitta}
+fi
+if [[ "$COMMAND" == *"vyos-xe-guest-utilities"* ]] && [[ "$COMMAND" == *"current"* ]]; then
+ COMMAND=${COMMAND//current/sagitta}
+fi
+
+/var/lib/jenkins/uncron/src/uncron-add "$COMMAND"
diff --git a/install-files/uncron-script.sh b/install-files/uncron-script.sh
new file mode 100755
index 0000000..3dd1916
--- /dev/null
+++ b/install-files/uncron-script.sh
@@ -0,0 +1,35 @@
+#!/usr/bin/env bash
+set -e
+
+# Ensure we are jenkins user
+if [ "$EUID" -ne 1006 ]
+ then echo "Please run as jenkins"
+ exit
+fi
+
+if [ -d uncron ]; then
+ echo "Updating Uncron git repository..."
+ cd uncron
+ git pull > /dev/null 2>&1
+else
+ echo "Cloning Uncron git repository..."
+ git clone https://github.com/vyos/uncron.git > /dev/null 2>&1
+ cd uncron
+fi
+
+if [ -d ~/.opam ]; then
+ echo "OPAM has already been initialized."
+else
+ echo "Initializing OPAM..."
+ opam init -n > /dev/null 2>&1
+fi
+
+eval $(opam env --switch=default)
+
+echo "Ensuring packages have been installed..."
+opam install lwt lwt_ppx logs containers -y > /dev/null 2>&1
+
+eval $(opam env)
+
+echo "Building Uncron..."
+dune build
diff --git a/install-files/uncron.service b/install-files/uncron.service
new file mode 100644
index 0000000..8f3290a
--- /dev/null
+++ b/install-files/uncron.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=Command Queue Service
+After=auditd.service systemd-user-sessions.service time-sync.target
+
+[Service]
+EnvironmentFile=/etc/uncron.conf
+ExecStart=/usr/local/sbin/uncron
+ExecReload=/bin/kill -HUP $MAINPID
+KillMode=process
+User=jenkins
+Group=jenkins
+Restart=on-failure
+RestartSec=5s
+
+[Install]
+WantedBy=multi-user.target
diff --git a/jobs/docker-container-jobs.json b/jobs/docker-container-jobs.json
new file mode 100644
index 0000000..dd58cc6
--- /dev/null
+++ b/jobs/docker-container-jobs.json
@@ -0,0 +1,14 @@
+[
+ {
+ "name": "vyos-build-container",
+ "description": "shared",
+ "gitUrl": "https://github.com/dd010101/vyos-build.git",
+ "branchRegex": "(equuleus|sagitta|current)",
+ "jenkinsfilePath": "packages/vyos-build-container/Jenkinsfile",
+ "branchParameters": {
+ "equuleus": {
+ "ELTS_MIRROR": "http://172.17.17.17:3142/deb.freexian.com/extended-lts"
+ }
+ }
+ }
+] \ No newline at end of file
diff --git a/jenkins-scripts/jobTemplate.xml b/jobs/jobTemplate.xml
index 2a41c69..2a41c69 100644
--- a/jenkins-scripts/jobTemplate.xml
+++ b/jobs/jobTemplate.xml
diff --git a/jobs/project-jobs.json b/jobs/project-jobs.json
new file mode 100644
index 0000000..968dbe8
--- /dev/null
+++ b/jobs/project-jobs.json
@@ -0,0 +1,443 @@
+[
+ {
+ "name": "aws-gateway-load-balancer-tunnel-handler",
+ "description": "sagitta-only",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "sagitta",
+ "jenkinsfilePath": "packages/aws-gateway-load-balancer-tunnel-handler/Jenkinsfile"
+ },
+ {
+ "name": "ddclient",
+ "description": "sagitta-only",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "sagitta",
+ "jenkinsfilePath": "packages/ddclient/Jenkinsfile"
+ },
+ {
+ "name": "dropbear",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "packages/dropbear/Jenkinsfile"
+ },
+ {
+ "name": "ethtool",
+ "description": "sagitta-only",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "sagitta",
+ "jenkinsfilePath": "packages/ethtool/Jenkinsfile"
+ },
+ {
+ "name": "frr",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "packages/frr/Jenkinsfile"
+ },
+ {
+ "name": "hostap",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "packages/hostap/Jenkinsfile"
+ },
+ {
+ "name": "hsflowd",
+ "description": "sagitta-only",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "sagitta",
+ "jenkinsfilePath": "packages/hsflowd/Jenkinsfile"
+ },
+ {
+ "name": "hvinfo",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/hvinfo.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "ipaddrcheck",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/ipaddrcheck.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "iproute2",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "equuleus",
+ "jenkinsfilePath": "packages/iproute2/Jenkinsfile"
+ },
+ {
+ "name": "isc-dhcp",
+ "description": "sagitta-only",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "sagitta",
+ "jenkinsfilePath": "packages/isc-dhcp/Jenkinsfile"
+ },
+ {
+ "name": "keepalived",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "packages/keepalived/Jenkinsfile"
+ },
+ {
+ "name": "libnss-mapuser",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/libnss-mapuser.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "libnss-tacplus",
+ "description": "sagitta-only",
+ "gitUrl": "https://github.com/dd010101/vyos-missing.git",
+ "branchRegex": "(sagitta)",
+ "jenkinsfilePath": "packages/libnss-tacplus/Jenkinsfile"
+ },
+ {
+ "name": "libpam-radius-auth",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/libpam-radius-auth.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "libvyosconfig",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/libvyosconfig.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "linux-kernel",
+ "description": "shared",
+ "gitUrl": "https://github.com/dd010101/vyos-build.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "packages/linux-kernel/Jenkinsfile"
+ },
+ {
+ "name": "live-boot",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/live-boot.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "mdns-repeater",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/mdns-repeater.git",
+ "branchRegex": "(equuleus)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "minisign",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "equuleus",
+ "jenkinsfilePath": "packages/minisign/Jenkinsfile"
+ },
+ {
+ "name": "ndppd",
+ "description": "sagitta-only",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "sagitta",
+ "jenkinsfilePath": "packages/ndppd/Jenkinsfile"
+ },
+ {
+ "name": "netfilter",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "packages/netfilter/Jenkinsfile"
+ },
+ {
+ "name": "ocserv",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "equuleus",
+ "jenkinsfilePath": "packages/ocserv/Jenkinsfile"
+ },
+ {
+ "name": "opennhrp",
+ "description": "sagitta-only",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "sagitta",
+ "jenkinsfilePath": "packages/opennhrp/Jenkinsfile"
+ },
+ {
+ "name": "openvpn-otp",
+ "description": "sagitta-only",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "sagitta",
+ "jenkinsfilePath": "packages/openvpn-otp/Jenkinsfile"
+ },
+ {
+ "name": "owamp",
+ "description": "sagitta-only",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "sagitta",
+ "jenkinsfilePath": "packages/owamp/Jenkinsfile"
+ },
+ {
+ "name": "pam_tacplus",
+ "description": "sagitta-only",
+ "gitUrl": "https://github.com/dd010101/vyos-build.git",
+ "branchRegex": "sagitta",
+ "jenkinsfilePath": "packages/pam_tacplus/Jenkinsfile"
+ },
+ {
+ "name": "pmacct",
+ "description": "sagitta-only",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "sagitta",
+ "jenkinsfilePath": "packages/pmacct/Jenkinsfile"
+ },
+ {
+ "name": "pyhumps",
+ "description": "sagitta-only",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "sagitta",
+ "jenkinsfilePath": "packages/pyhumps/Jenkinsfile"
+ },
+ {
+ "name": "python3-inotify",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/dd010101/vyos-missing.git",
+ "branchRegex": "equuleus",
+ "jenkinsfilePath": "packages/python3-inotify/Jenkinsfile"
+ },
+ {
+ "name": "radvd",
+ "description": "sagitta-only",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "sagitta",
+ "jenkinsfilePath": "packages/radvd/Jenkinsfile"
+ },
+ {
+ "name": "strongswan",
+ "description": "sagitta-only",
+ "gitUrl": "https://github.com/dd010101/vyos-build.git",
+ "branchRegex": "sagitta",
+ "jenkinsfilePath": "packages/strongswan/Jenkinsfile"
+ },
+ {
+ "name": "telegraf",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyos-build.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "packages/telegraf/Jenkinsfile"
+ },
+ {
+ "name": "udp-broadcast-relay",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/udp-broadcast-relay.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-bash",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyatta-bash.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-biosdevname",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyatta-biosdevname.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-cfg-firewall",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyatta-cfg-firewall.git",
+ "branchRegex": "(equuleus)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-cfg-qos",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyatta-cfg-qos.git",
+ "branchRegex": "(equuleus)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-cfg-quagga",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyatta-cfg-quagga.git",
+ "branchRegex": "(equuleus)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-cfg-system",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyatta-cfg-system.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-cfg-vpn",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyatta-cfg-vpn.git",
+ "branchRegex": "(equuleus)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-cfg",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyatta-cfg.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-cluster",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyatta-cluster.git",
+ "branchRegex": "(equuleus)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-config-mgmt",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyatta-config-mgmt.git",
+ "branchRegex": "(equuleus)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-conntrack",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyatta-conntrack.git",
+ "branchRegex": "(equuleus)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-nat",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyatta-nat.git",
+ "branchRegex": "(equuleus)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-op-firewall",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyatta-op-firewall.git",
+ "branchRegex": "(equuleus)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-op-qos",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyatta-op-qos.git",
+ "branchRegex": "(equuleus)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-op-vpn",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyatta-op-vpn.git",
+ "branchRegex": "(equuleus)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-op",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyatta-op.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-wanloadbalance",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyatta-wanloadbalance.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyatta-zone",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyatta-zone.git",
+ "branchRegex": "(equuleus)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyos-1x",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyos-1x.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyos-cloud-init",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyos-cloud-init.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyos-http-api-tools",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyos-http-api-tools.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyos-nhrp",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyos-nhrp.git",
+ "branchRegex": "(equuleus)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyos-opennhrp",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyos-opennhrp.git",
+ "branchRegex": "(equuleus)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyos-strongswan",
+ "description": "equuleus-only",
+ "gitUrl": "https://github.com/vyos/vyos-strongswan.git",
+ "branchRegex": "(equuleus)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyos-user-utils",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyos-user-utils.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyos-utils",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyos-utils.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyos-world",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyos-world.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "vyos-xe-guest-utilities",
+ "description": "shared",
+ "gitUrl": "https://github.com/vyos/vyos-xe-guest-utilities.git",
+ "branchRegex": "(equuleus|current)",
+ "jenkinsfilePath": "Jenkinsfile"
+ },
+ {
+ "name": "wide-dhcpv6",
+ "description": "shared",
+ "gitUrl": "https://github.com/dd010101/vyos-build.git",
+ "branchRegex": "(equuleus|sagitta)",
+ "jenkinsfilePath": "packages/wide-dhcpv6/Jenkinsfile"
+ }
+]