diff --git a/jobs/templates/debian/automatic-backport.groovy b/jobs/templates/debian/automatic-backport.groovy new file mode 100644 index 0000000..f4b7927 --- /dev/null +++ b/jobs/templates/debian/automatic-backport.groovy @@ -0,0 +1,127 @@ +def repo_name = '{display-name}' + +def environment + +def release +switch (params.DESTINATION) {{ + case ~/^stretch(-.*|)$/: + release = 9 + break + case ~/^buster(-.*|)$/: + release = 10 + break + case ~/^bullseye(-.*|)$/: + release = 11 + break + case ~/^bookworm(-.*|)$/: + release = 12 + break + default: + release = 'UNKNOWN' + break +}} + +def backport_ok = false + +pipeline {{ + agent {{ label 'debian' }} + stages {{ + stage('Checkout') {{ + steps {{ + cleanWs() + checkout([ + $class: 'GitSCM', + branches: [[name: "debian/${{params.DESTINATION}}"], [name: "refs/tags/${{params.GIT_TAG}}"]], + userRemoteConfigs: [[ + url: "https://forge.softwareheritage.org/source/${{repo_name}}.git", + ]], + ]) + }} + }} + stage('Check the source branch') {{ + steps {{ + script {{ + def current_release = sh( + script: "dpkg-parsechangelog -SDistribution", + returnStdout: true, + ).trim(); + + backport_ok = current_release == params.SOURCE && release != 'UNKNOWN' + }} + }} + }} + stage('Seed the environment') {{ + when {{ + beforeAgent true + expression {{ backport_ok }} + }} + steps {{ + script {{ + def hostname = sh( + script: "hostname --fqdn", + returnStdout: true, + ).trim(); + + def short_hostname = hostname - '.internal.softwareheritage.org'; + + environment = [ + "DEBEMAIL=jenkins@${{hostname}}", + "DEBFULLNAME=Software Heritage autobuilder (on ${{short_hostname}})", + ] + }} + }} + }} + stage('Merge package version to destination branch') {{ + when {{ + beforeAgent true + expression {{ backport_ok }} + }} + steps {{ + withEnv(environment) {{ + sh """ + git checkout debian/${{params.DESTINATION}} + git merge ${{params.GIT_TAG}} --no-commit --no-edit || true + git checkout ${{params.GIT_TAG}} -- debian/changelog + git add debian/changelog + git commit --no-verify --no-edit + git show + """ + }} + }} + }} + stage('Update changelog for backport') {{ + when {{ + beforeAgent true + expression {{ backport_ok }} + }} + steps {{ + withEnv(environment) {{ + sh """ + dch -l ~bpo${{release}}+ -D ${{params.DESTINATION}} --force-distribution 'Rebuild for ${{params.DESTINATION}}' + git add debian/changelog + git commit --no-verify -m "Updated backport on ${{params.DESTINATION}} from ${{params.GIT_TAG}} (${{params.SOURCE}})" + git show + """ + }} + }} + }} + stage('Upload changes') {{ + when {{ + beforeAgent true + expression {{ backport_ok }} + }} + steps {{ + sshagent (credentials: ['jenkins-public-ci-ssh']) {{ + script {{ + def git_push = 'git push --follow-tags --all' + if (params.DRY_RUN) {{ + git_push += ' -n' + }} + + sh(script: git_push) + }} + }} + }} + }} + }} +}} diff --git a/jobs/templates/debian/automatic-backport.yaml b/jobs/templates/debian/automatic-backport.yaml new file mode 100644 index 0000000..a4c49c4 --- /dev/null +++ b/jobs/templates/debian/automatic-backport.yaml @@ -0,0 +1,39 @@ +- job-template: + name: 'debian/packages/{name}/automatic-backport' + description: | + Backport Debian package to the given release + project-type: pipeline + parameters: + - git-parameter: + name: GIT_TAG + description: git tag to backport + type: PT_TAG + sortMode: DESCENDING_SMART + selectedValue: TOP + tagFilter: debian/.* + - choice: + name: SOURCE + description: check that the source branch corresponds to this before issuing the backport + choices: + - unstable-swh + - unstable + - bookworm-swh + - bullseye-swh + - buster-swh + - stretch-swh + default: unstable-swh + - choice: + name: DESTINATION + description: the destination branch the backport targets + choices: + - stretch-swh + - buster-swh + - bullseye-swh + - bookworm-swh + default: stretch-swh + - bool: + name: DRY_RUN + description: Don't push the resulting changes to a Debian branch + default: false + dsl: + !include-raw: automatic-backport.groovy diff --git a/jobs/templates/incoming-tag.groovy b/jobs/templates/incoming-tag.groovy index 4e028c4..0c97594 100644 --- a/jobs/templates/incoming-tag.groovy +++ b/jobs/templates/incoming-tag.groovy @@ -1,78 +1,79 @@ import jenkins.model.Jenkins @NonCPS def job_exists(name) {{ def instance = jenkins.model.Jenkins.instance return instance.getItemByFullName(name) != null }} pipeline {{ agent none stages {{ stage('Refresh tag list') {{ agent any steps {{ checkout([ $class: 'GitSCM', userRemoteConfigs: [[ url: 'https://forge.softwareheritage.org/source/{display-name}.git', ]], branches: [[ name: params.GIT_TAG, ]], browser: [ $class: 'Phabricator', repo: '{display-name}', repoUrl: 'https://forge.softwareheritage.org/', ], ]) }} }} stage('Build and upload PyPI package') {{ when {{ expression {{ params.GIT_TAG =~ /^v\d+(.\d+)+$/ }} expression {{ job_exists('/{name}/pypi-upload') }} }} steps {{ build( job: '/{name}/pypi-upload', parameters: [ string(name: 'GIT_TAG', value: params.GIT_TAG), string(name: 'PYPI_HOST', value: '{incoming-tag-auto-pypi-host}'), ], ) }} }} stage('Debian packaging for new release') {{ when {{ expression {{ params.GIT_TAG =~ /^v\d+(.\d+)+$/ }} expression {{ job_exists('/debian/packages/{name}/update-for-release') }} }} steps {{ build( job: '/debian/packages/{name}/update-for-release', parameters: [ string(name: 'GIT_TAG', value: params.GIT_TAG), ], wait: false, ) }} }} - stage('Debian automatic build') {{ + stage('Debian automatic backport') {{ when {{ expression {{ params.GIT_TAG =~ /^debian\/.*$/ }} - expression {{ job_exists('/debian/packages/{name}/build') }} + expression {{ params.GIT_TAG !~ /^debian\/upstream\/.*$/ }} + expression {{ params.GIT_TAG !~ /_bpo/ }} + expression {{ job_exists('/debian/packages/{name}/automatic-backport') }} }} steps {{ - build( - job: '/debian/packages/{name}/build', + build( + job: '/debian/packages/{name}/automatic-backport', parameters: [ string(name: 'GIT_TAG', value: params.GIT_TAG), - booleanParam(name: 'UPLOAD', value: true), ], wait: false, ) }} }} }} }}