diff options
author | Bjarke Istrup Pedersen <gurli@gurlinet.dk> | 2024-05-28 21:20:55 +0200 |
---|---|---|
committer | Bjarke Istrup Pedersen <gurli@gurlinet.dk> | 2024-06-30 16:08:05 +0200 |
commit | aa44b2565f4191a1c90d755a6dde2b7c8f23f6d7 (patch) | |
tree | 597a07b67701f87aaf848744bdff83994bffebc3 | |
parent | 4d4047656329660d5ab75c3e34d9df902eb3d2fa (diff) | |
download | vyos-jenkins-aa44b2565f4191a1c90d755a6dde2b7c8f23f6d7.tar.gz vyos-jenkins-aa44b2565f4191a1c90d755a6dde2b7c8f23f6d7.zip |
Implement install scripts
-rw-r--r-- | .gitignore | 1 | ||||
-rwxr-xr-x | 1-prereqs.sh | 251 | ||||
-rwxr-xr-x | 2-jenkins.sh | 345 | ||||
-rwxr-xr-x | 3-repositories.sh | 110 | ||||
-rwxr-xr-x | 4-uncron.sh | 90 | ||||
-rwxr-xr-x | 5-docker-jobs.sh | 59 | ||||
-rwxr-xr-x | 6-provision-project-jobs.sh | 45 | ||||
-rwxr-xr-x | 7-build-project-jobs.sh | 55 | ||||
-rwxr-xr-x | 8-nginx.sh | 81 | ||||
-rw-r--r-- | helper-logic | 584 | ||||
-rw-r--r-- | install-files/daemon.json | 5 | ||||
-rw-r--r-- | install-files/dummy0.interface | 4 | ||||
-rwxr-xr-x | install-files/gpg-script.sh | 24 | ||||
-rw-r--r-- | install-files/nginx-site | 21 | ||||
-rw-r--r-- | install-files/org.jenkinsci.plugins.docker.workflow.declarative.GlobalConfig.xml | 5 | ||||
-rw-r--r-- | install-files/org.jenkinsci.plugins.workflow.libs.GlobalLibraries.xml | 4 | ||||
-rwxr-xr-x | install-files/ssh-script.sh | 25 | ||||
-rwxr-xr-x | install-files/uncron-add | 21 | ||||
-rwxr-xr-x | install-files/uncron-script.sh | 35 | ||||
-rw-r--r-- | install-files/uncron.service | 16 | ||||
-rw-r--r-- | jobs/docker-container-jobs.json | 14 | ||||
-rw-r--r-- | jobs/jobTemplate.xml (renamed from jenkins-scripts/jobTemplate.xml) | 0 | ||||
-rw-r--r-- | jobs/project-jobs.json | 443 |
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" + } +] |