diff --git a/jobs/tools/jenkins-jobs-builder.groovy.j2 b/jobs/tools/jenkins-jobs-builder.groovy.j2 index 5cf4bd6..60dbe74 100644 --- a/jobs/tools/jenkins-jobs-builder.groovy.j2 +++ b/jobs/tools/jenkins-jobs-builder.groovy.j2 @@ -1,56 +1,59 @@ pipeline { agent any stages { stage('Checkout Repository') { steps { updateGitlabCommitStatus name: 'jenkins', state: 'running' checkout([ $class: 'GitSCM', branches: [[name: env.gitlabSourceBranch ?: "master"]], userRemoteConfigs: [[ url: '{{gitlab_url}}/{{gitlab_project_name}}.git', refspec: '+refs/heads/*:refs/remotes/origin/* \ +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*' ]], ]) } } stage('Test Jenkins jobs can be generated') { steps { sh('tox') } } stage('Update Jenkins jobs and setup gitlab webhooks') { when { // really update jenkins jobs configuration when pushing commits to master // or when manually triggering the job from Jenkins UI expression { !env.gitlabMergeRequestIid } anyOf { expression { !env.gitlabSourceBranch } expression { "${env.gitlabSourceBranch}" == "master" } } } steps { script { sh('tox -- update --delete-old') + build( + job: '/jenkins-tools/setup-gitlab-webhooks', + ) } } } } post { failure { updateGitlabCommitStatus name: 'jenkins', state: 'failed' } success { updateGitlabCommitStatus name: 'jenkins', state: 'success' } aborted { updateGitlabCommitStatus name: 'jenkins', state: 'canceled' } } } diff --git a/jobs/tools/setup-gitlab-webhooks.groovy.j2 b/jobs/tools/setup-gitlab-webhooks.groovy.j2 new file mode 100644 index 0000000..900fc30 --- /dev/null +++ b/jobs/tools/setup-gitlab-webhooks.groovy.j2 @@ -0,0 +1,84 @@ +pipeline { + agent any + + environment { + GITLAB_TOKEN = credentials("jenkins-gitlab-token") + } + + stages { + + stage('Checkout Repository') { + steps { + checkout([ + $class: 'GitSCM', + branches: [[name: 'master']], + userRemoteConfigs: [[ + url: "http://forge.softwareheritage.org/source/swh-jenkins-jobs.git", + ]], + ]) + } + } + + stage('Setup gitlab integration') { + steps { + script { + setupGitlabWebhook("swh/infra/ci-cd/swh-jenkins-jobs", + "jenkins-tools/swh-jenkins-jobs-builder", + true, true, false) + + projects = readYaml(file: 'jobs/swh-packages.yaml') + for (project in projects) { + if (project.containsKey("project")) { + def jenkinsFolder = project.get('project').get('name') + def repoName= project.get('project').get('repo_name') + def gitlabProjectName = "swh/devel/${repoName}" + setupGitlabWebhook(gitlabProjectName, "${jenkinsFolder}/gitlab-tests") + } + } + } + } + } + } +} + +void setupGitlabWebhook(gitlabProjectName, jenkinsProjectName, pushEvents = true, + mergeRequestEvents = true, tagPushEvents = false) { + + def webhookUrl = "${jenkins_url}/project/${jenkinsProjectName}" + def gitlabProjectEncoded = java.net.URLEncoder.encode(gitlabProjectName, "UTF-8") + def payload = """ + { + "id": "${gitlabProjectEncoded}", + "url": "${webhookUrl}", + "push_events": "${pushEvents}", + "merge_requests_events": "${mergeRequestEvents}", + "tag_push_events": "${tagPushEvents}", + "token": "{{jenkins_token}}" + } + """ + + def url = "${gitlab_url}/api/v4/projects/${gitlabProjectEncoded}/hooks" + + // get current webhooks of the gitlab project + def response = httpRequest httpMode: 'GET', url: url, + contentType: 'APPLICATION_JSON', + customHeaders: [[name: 'Authorization', value: "Bearer $GITLAB_TOKEN"]] + + def hooks = readJSON text: response.content + for (hook in hooks) { + if (hook.url == webhookUrl) { + // update previously set webhook for jenkins job + httpRequest httpMode: 'PUT', url: "${url}/${hook.id}", + contentType: 'APPLICATION_JSON', requestBody: payload, + customHeaders: [[name: 'Authorization', value: "Bearer $GITLAB_TOKEN"]] + return + } + } + + // add webhook for jenkins job + httpRequest httpMode: 'POST', url: url, + contentType: 'APPLICATION_JSON', requestBody: payload, + customHeaders: [[name: 'Authorization', value: "Bearer $GITLAB_TOKEN"]] + +} + diff --git a/jobs/tools/setup-gitlab-webhooks.yaml b/jobs/tools/setup-gitlab-webhooks.yaml new file mode 100644 index 0000000..f5eba6c --- /dev/null +++ b/jobs/tools/setup-gitlab-webhooks.yaml @@ -0,0 +1,25 @@ +- job-template: + name: jenkins-tools/{name} + project-type: pipeline + description: Setup Jenkins integration for a GitLab repository + node: built-in + # secret jenkins token is generated when executing tox + jenkins_token: !include-raw: jobs/templates/jenkins-token + parameters: + - string: + name: gitlab_url + description: URL of GitLab instance + default: https://gitlab-staging.swh.network + - string: + name: jenkins_url + description: URL of Jenkins instance + default: https://jenkins.softwareheritage.org + + dsl: !include-jinja2: setup-gitlab-webhooks.groovy.j2 + +# we use a project and a job template here as we need jinja2 processing +# to inline the generated jenkins token into the pipeline groovy script +- project: + name: setup-gitlab-webhooks + jobs: + - "jenkins-tools/{name}"