name: "Ubuntu packaging" run-name: "Ubuntu packaging - ${{ github.event.client_payload.branch }} (branch ${{ github.event.client_payload.baseBranch }}), by @${{ github.event.client_payload.user }}" on: repository_dispatch: types: ['deb-release-packaging:*', 'deb-pr-packaging:*'] # Input: # buildSha: The SHA of the commit to build, e.g. of the branch or # refs/pull/1234/head for PR # branch: The branch to build, for a PR in the form `PR-1234` # baseBranch: For a PR the base branch, otherwise the same as `branch` # baseRef: The ref of the previous commit. For a PR the same as `baseBranch`. # user: The user that triggered the build or created the PR # isTestBuild: false for Releases, otherwise true env: COLOR_GREEN: "\e[32m" GH_TOKEN: ${{ github.token }} STATUS_CONTEXT: 'Debian Packaging' DEBFULLNAME: 'Keyman GHA packager' DEBEMAIL: 'support@keyman.com' jobs: sourcepackage: name: Build source package if: github.repository == 'keymanapp/keyman' runs-on: ubuntu-22.04 outputs: VERSION: ${{ steps.version_step.outputs.VERSION }} PRERELEASE_TAG: ${{ steps.prerelease_tag.outputs.PRERELEASE_TAG }} steps: - name: Checkout uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c #v3.3.0 with: ref: '${{ github.event.client_payload.buildSha }}' - name: Set pending status on PR builds id: set_status if: github.event.client_payload.isTestBuild == 'true' shell: bash run: | gh api \ --method POST \ -H "Accept: application/vnd.github+json" \ /repos/$GITHUB_REPOSITORY/statuses/${{ github.event.client_payload.buildSha }} \ -f state='pending' \ -f target_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \ -f description='Debian packaging started' \ -f context="$STATUS_CONTEXT" - name: Install devscripts uses: ./.github/actions/apt-install with: packages: devscripts equivs - name: Install dependencies run: | cd linux ./scripts/deb-packaging.sh --gha dependencies - name: Build source package id: build_source_package run: | export TIER=$(cat TIER.md) export GHA_TEST_BUILD="${{ github.event.client_payload.isTestBuild }}" export GHA_BRANCH="${{ github.event.client_payload.branch }}" echo "TIER=$TIER" >> $GITHUB_ENV echo "GHA_TEST_BUILD=${GHA_TEST_BUILD}" >> $GITHUB_ENV echo "GHA_BRANCH=${GHA_BRANCH}" >> $GITHUB_ENV cd linux ./scripts/deb-packaging.sh --gha source - name: Set version as output parameter id: version_step shell: bash run: | THIS_SCRIPT="$GITHUB_WORKSPACE/.github/workflows/deb-packaging.yml" . "${THIS_SCRIPT%/*}/../../resources/build/build-utils.sh" echo "VERSION=$VERSION" >> $GITHUB_OUTPUT - name: Set prerelease tag as output parameter id: prerelease_tag shell: bash run: | if [ "${{ github.event.client_payload.isTestBuild }}" == "true" ]; then PRERELEASE_TAG="~${{ github.event.client_payload.branch }}-$GITHUB_RUN_NUMBER.$GITHUB_RUN_ATTEMPT" else PRERELEASE_TAG="" fi echo "PRERELEASE_TAG=$PRERELEASE_TAG" >> $GITHUB_OUTPUT - name: Output which branch or PR we're building plus name of .dsc file run: | if [ "${{ github.event.client_payload.isTestBuild }}" == "true" ]; then echo ":checkered_flag: **Test build of version ${{ steps.version_step.outputs.VERSION }} for ${{ github.event.client_payload.branch }}**" >> $GITHUB_STEP_SUMMARY else echo ":ship: **Release build of ${{ github.event.client_payload.branch }} branch (${{ github.event.client_payload.branch}}), version ${{ steps.version_step.outputs.VERSION }}**" >> $GITHUB_STEP_SUMMARY fi echo "" >> $GITHUB_STEP_SUMMARY echo ":gift: Generated source package:" >> $GITHUB_STEP_SUMMARY echo "- $(find . -name keyman_\*.dsc)" >> $GITHUB_STEP_SUMMARY - name: Store source package uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: keyman-srcpkg path: | keyman_* debian/***/* if: always() binary_packages: name: Build binary packages needs: sourcepackage strategy: fail-fast: true matrix: dist: [focal, jammy, mantic, noble] arch: [amd64] runs-on: ubuntu-latest steps: - name: Download Artifacts uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: keyman-srcpkg path: artifacts/keyman-srcpkg - name: Build uses: sillsdev/gha-ubuntu-packaging@1f4b7e7eacb8c82a4d874ee2c371b9bfef7e16ea # v1.0 with: dist: "${{ matrix.dist }}" platform: "${{ matrix.arch }}" source_dir: "artifacts/keyman-srcpkg" sourcepackage: "keyman_${{ needs.sourcepackage.outputs.VERSION }}-1.dsc" deb_fullname: ${{env.DEBFULLNAME}} deb_email: ${{env.DEBEMAIL}} prerelease_tag: ${{ needs.sourcepackage.outputs.PRERELEASE_TAG }} - name: Output resulting .deb files run: | echo '```' >> $GITHUB_STEP_SUMMARY echo "$(find artifacts/ -name \*.deb)" >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY - name: Store binary packages uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: keyman-binarypkgs-${{ matrix.dist }}_${{ matrix.arch }} path: | artifacts/* !artifacts/keyman-srcpkg/ if: always() deb_signing: name: Sign source and binary packages needs: [sourcepackage, binary_packages] runs-on: ubuntu-latest environment: "deploy (linux)" if: github.event.client_payload.isTestBuild == 'false' steps: - name: Sign packages uses: sillsdev/gha-deb-signing@a38dbde6bc9afabede5e07609105acc83c760ad4 # v0.6 with: src-pkg-name: "keyman_${{ needs.sourcepackage.outputs.VERSION }}-1_source.changes" bin-pkg-name: "keyman_${{ needs.sourcepackage.outputs.VERSION }}-1${{ needs.sourcepackage.outputs.PRERELEASE_TAG }}+" artifacts-prefix: "keyman-" artifacts-result-name: "keyman-signedpkgs" gpg-signing-key: "${{ secrets.GPG_SIGNING_KEY }}" debsign-keyid: "${{ secrets.DEBSIGN_KEYID }}" upload-to-llso: name: Upload packages to llso needs: [sourcepackage, deb_signing] runs-on: self-hosted environment: "deploy (linux)" if: github.event.client_payload.isTestBuild == 'false' steps: - name: Install dput run: | export DEBIAN_FRONTEND=noninteractive export DEBIAN_PRIORITY=critical export DEBCONF_NOWARNINGS=yes sudo apt-get update sudo apt-get install -q -y dput - name: Setup .dput.cf run: | echo "${{vars.ENV_DPUT_CONFIG}}" > ~/.dput.cf - name: Configure GPG Key shell: bash run: | echo -e "::group::\e[32mConfigure GPG key" echo -n "${{ secrets.GPG_SIGNING_KEY }}" | base64 --decode | gpg --import echo "${{ secrets.DEBSIGN_KEYID }}:6:" | gpg --import-ownertrust echo "::endgroup::" - name: Download Artifacts uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: keyman-signedpkgs - name: Upload run: | function dput_retry() { local i=1 local retval local upload_log=$1 local hosttarget=$2 local max_retries=10 local tmpfile=/tmp/dput.output shift 2 while ((i <= max_retries)); do dput ${upload_log} ${hosttarget} "$@" 2>&1 | tee ${tmpfile} retval=$? echo "dput exited with ${retval}" if ! grep -q "ssh: Could not resolve hostname package-drop.psonet: Name or service not known" ${tmpfile}; then rm ${tmpfile} if [[ ${retval} != 0 ]]; then exit ${retval} else return 0 fi fi if ((++i <= max_retries)); then sleep 10 echo "${COLOR_BLUE}Retry ${i}/${max_retries}:" fi done rm ${tmpfile} exit ${retval} } case ${{ github.event.client_payload.branch }} in stable-*) destination='' ;; beta) destination='-proposed' ;; *) destination='-experimental' ;; esac echo -e "::group::${COLOR_GREEN}Upload source package" dput_retry -U llso:ubuntu/jammy${destination} *_source.changes echo "::endgroup::" echo -e "::group::${COLOR_GREEN}Uploading binary packages" pattern="keyman_${{ needs.sourcepackage.outputs.VERSION }}.+\+(.*)[0-9]_[^.]+.changes" for f in *_amd64.changes; do if [[ $f =~ $pattern ]]; then dist=${BASH_REMATCH[1]} dput_retry -U llso:ubuntu/${dist}${destination} $f fi done echo "::endgroup::" api_verification: name: Verify API for libkeymancore.so needs: [sourcepackage, binary_packages] runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1 with: ref: '${{ github.event.client_payload.buildSha }}' fetch-depth: 0 - name: Download Artifacts uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: path: artifacts merge-multiple: true - name: Install devscripts uses: ./.github/actions/apt-install with: packages: devscripts equivs - name: Verify API run: | cd linux PKG_NAME=libkeymancore ./scripts/deb-packaging.sh \ --gha \ --bin-pkg "${GITHUB_WORKSPACE}/artifacts/${PKG_NAME}_${{ needs.sourcepackage.outputs.VERSION }}-1${{ needs.sourcepackage.outputs.PRERELEASE_TAG }}+jammy1_amd64.deb" \ --git-sha "${{ github.event.client_payload.buildSha }}" \ --git-base "${{ github.event.client_payload.baseRef }}" \ verify 2>> $GITHUB_STEP_SUMMARY - name: Archive .symbols file uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: libkeymancore.symbols path: linux/debian/tmp/DEBIAN/symbols if: always() set_status: name: Set result status on PR builds needs: [sourcepackage, binary_packages, api_verification] runs-on: ubuntu-latest if: ${{ always() && github.event.client_payload.isTestBuild == 'true' }} steps: - name: Set success if: needs.sourcepackage.result == 'success' && needs.binary_packages.result == 'success' && needs.api_verification.result == 'success' run: | echo "RESULT=success" >> $GITHUB_ENV echo "MSG=Package build succeeded" >> $GITHUB_ENV - name: Set cancelled if: needs.sourcepackage.result == 'cancelled' || needs.binary_packages.result == 'cancelled' || needs.api_verification.result == 'cancelled' run: | echo "RESULT=error" >> $GITHUB_ENV echo "MSG=Package build cancelled" >> $GITHUB_ENV - name: Set failure if: needs.sourcepackage.result == 'failure' || needs.binary_packages.result == 'failure' || needs.api_verification.result == 'failure' run: | echo "RESULT=failure" >> $GITHUB_ENV echo "MSG=Package build failed" >> $GITHUB_ENV - name: Set final status run: | gh api \ --method POST \ -H "Accept: application/vnd.github+json" \ /repos/$GITHUB_REPOSITORY/statuses/${{ github.event.client_payload.buildSha }} \ -f state="$RESULT" \ -f target_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \ -f description="$MSG" \ -f context="$STATUS_CONTEXT"