#!/usr/bin/env bash set -e # # This script seeds Jenkins jobs via list of packages in jobs.json # it iterates through all packages # it checks if job for package exists # it updates job if exists otherwise creates new one. # It can also start build for all jobs. # # This script has two modes, first mode is create # ./seed-jobs.sh create # this will update or create jobs # # Second mode is build # ./seed-jobs.sh build # this will trigger build for all jobs # # You need to wait after create some time, Jenkins need to complete branch indexing. # Check Jenkins Build Queue and Build Executor Status to be empty. Then you can run build. # # dependency: apt install -y xmlstarlet jq # # Refer to Jenkins documentation to create a token # https://www.jenkins.io/doc/book/system-administration/authenticating-scripted-clients/ # The API token is available in your personal configuration page. # Click your name on the top right corner on every page, then click "Configure" # to see your API token. jenkinsUser="" # fill your username here or set via export JENKINS_USER jenkinsToken="" # fill your token here or set via export JENKINS_TOKEN jenkinsHost="172.17.17.17:8080" workDir="/tmp/seed-jobs" mkdir -p "$workDir" templatePath="../jobs/jobTemplate.xml" dockerContainerJobsPath="../jobs/docker-container-jobs.json" projectsJobsPath="../jobs/project-jobs.json" jenkinsUser=${jenkinsUser:-$JENKINS_USER} jenkinsToken=${jenkinsToken:-$JENKINS_TOKEN} jenkinsUrl="http://${jenkinsUser}:${jenkinsToken}@$jenkinsHost" selectedBranch="$BRANCH" mode="$1" availableModes=("create" "build") get() { curl -sS -g --fail-with-body "${jenkinsUrl}${1}" } post() { curl -sS -g --fail-with-body -X POST "${jenkinsUrl}${1}" } push() { curl -sS -g --fail-with-body -X POST -d "@${2}" -H "Content-Type: text/xml" "${jenkinsUrl}${1}" } echo -n "testing jenkins connection: " get > /dev/null echo "ok" excludedDescription="" if [ "$selectedBranch" == "sagitta" ]; then excludedDescription="equuleus-only" elif [ "$selectedBranch" == "equuleus" ]; then excludedDescription="sagitta-only" else if [ "$selectedBranch" != "" ]; then >&2 echo -e "ERROR: Unknown branch: $selectedBranch, please provide valid \$BRANCH (sagitta or equuleus)" exit 1 fi fi if [[ "$mode" == "create" ]]; then jobsPath="$workDir/jobs.json" cat "$dockerContainerJobsPath" "$projectsJobsPath" | jq -s 'add' > "$jobsPath" while read item do jobName=$(echo "$item" | jq -r .name) echo -n "$jobName:" description=$(echo "$item" | jq -r .description) gitUrl=$(echo "$item" | jq -r .gitUrl) branchRegex=$(echo "$item" | jq -r .branchRegex) jenkinsfilePath=$(echo "$item" | jq -r .jenkinsfilePath) if [ "$description" == "$excludedDescription" ]; then echo " excluded ($description)" continue fi # create job.xml by using jobTemplate.xml jobPath="$workDir/$jobName.xml" project="org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject" branchSource="$project/sources/data/jenkins.branch.BranchSource/source" regexTrait="$branchSource/traits/jenkins.scm.impl.trait.RegexSCMHeadFilterTrait" xmlstarlet ed --update "//$project/description" --value "$description" \ --update "//$branchSource/remote" --value "$gitUrl" \ --update "//$regexTrait/regex" --value "$branchRegex" \ --update "//$project/factory/scriptPath" --value "$jenkinsfilePath" \ "$templatePath" > "$jobPath" 2>/dev/null # check if job exists result=$(get "/checkJobName?value=$jobName" || true) if [[ "$result" == *"already exists"* ]]; then # update job push "/job/$jobName/config.xml" "$jobPath" else # create job push "/createItem?name=$jobName" "$jobPath" fi echo " ok" done < <(cat "$jobsPath" | jq -c '.[]') elif [[ "$mode" == "build" ]]; then get "/api/xml?tree=jobs[name]" | xmlstarlet sel -t -v "//hudson/job/name" | while read jobName || [ -n "$jobName" ]; do echo -n "$jobName:" # trigger build - it's not easy to know what branches job has # thus we trigger all possible ones and ignore not found post "/job/$jobName/job/equuleus/build" > /dev/null 2>/dev/null || true post "/job/$jobName/job/sagitta/build" > /dev/null 2>/dev/null || true post "/job/$jobName/job/current/build" > /dev/null 2>/dev/null || true echo " ok" done else >&2 echo "ERROR: unknown mode '$mode'" echo "available modes: ${availableModes[*]}" exit 1 fi