name: release on: push: tags: ['v*'] workflow_dispatch: inputs: dry_run: description: >- Build the repositories with a throwaway key and install from them, without publishing anything. This is how the release path gets exercised without cutting a tag. type: boolean default: false permissions: contents: write jobs: deb: name: Debian package runs-on: ubuntu-latest container: debian:stable steps: - name: Install the build tools run: | apt-get update -qq apt-get install -y --no-install-recommends \ ca-certificates git make gettext scdoc dpkg-dev - uses: actions/checkout@v7 - name: Check the tag against the Makefile run: packaging/check-version.sh "${{ github.ref_name }}" - run: packaging/build-deb.sh - name: Look inside what was built run: | dpkg-deb --info dist/*.deb dpkg-deb --contents dist/*.deb - uses: actions/upload-artifact@v7 with: name: deb path: dist/*.deb if-no-files-found: error rpm: name: RPM package runs-on: ubuntu-latest container: fedora:latest steps: - name: Install the build tools run: | dnf install -y --setopt=install_weak_deps=False \ git make gettext scdoc tar rpm-build rpm-sign systemd-rpm-macros - uses: actions/checkout@v7 - name: Check the tag against the Makefile run: packaging/check-version.sh "${{ github.ref_name }}" - run: packaging/build-rpm.sh # Signed here rather than alongside the APT repository, because this is # the one place with a native rpm-sign. A dry run signs with a key it # makes on the spot, so the command itself is still exercised. - name: Sign the package env: GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} DRY_RUN: ${{ inputs.dry_run }} run: | if [ "$DRY_RUN" = "true" ]; then gpg --batch --passphrase '' --quick-generate-key \ 'dry run ' rsa2048 sign never elif [ -n "${GPG_PRIVATE_KEY:-}" ]; then printf '%s' "$GPG_PRIVATE_KEY" | gpg --batch --import else echo "No GPG_PRIVATE_KEY secret; leaving the package unsigned." exit 0 fi keyid="$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/ { print $5; exit }')" rpmsign --define "_gpg_name $keyid" --addsign dist/*.rpm gpg --armor --export "$keyid" > dist/rpm-signer.asc rpm --import dist/rpm-signer.asc rpm --checksig dist/*.rpm - name: Look inside what was built run: | rpm -qip dist/*.rpm rpm -qlp dist/*.rpm - uses: actions/upload-artifact@v7 with: name: rpm path: | dist/*.rpm dist/rpm-signer.asc if-no-files-found: error publish: name: Release and repositories needs: [deb, rpm] if: startsWith(github.ref, 'refs/tags/v') || inputs.dry_run runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - uses: actions/download-artifact@v8 with: path: incoming merge-multiple: true - name: Attach the packages to the release if: ${{ !inputs.dry_run }} env: GH_TOKEN: ${{ github.token }} run: | gh release create "${{ github.ref_name }}" \ --title "${{ github.ref_name }}" \ --generate-notes \ incoming/*.deb incoming/*.rpm \ || gh release upload "${{ github.ref_name }}" \ incoming/*.deb incoming/*.rpm --clobber - name: Install the repository tools run: | sudo apt-get update -qq sudo apt-get install -y --no-install-recommends \ dpkg-dev apt-utils createrepo-c - name: Get a signing key id: key env: GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} DRY_RUN: ${{ inputs.dry_run }} run: | if [ "$DRY_RUN" = "true" ]; then gpg --batch --passphrase '' --quick-generate-key \ 'dry run ' rsa2048 sign never elif [ -n "${GPG_PRIVATE_KEY:-}" ]; then printf '%s' "$GPG_PRIVATE_KEY" | gpg --batch --import else echo "present=no" >> "$GITHUB_OUTPUT" echo "::warning::No GPG_PRIVATE_KEY secret - the apt and dnf repositories were not updated. The packages are on the release." exit 0 fi echo "present=yes" >> "$GITHUB_OUTPUT" - name: Check out the published repositories if: steps.key.outputs.present == 'yes' && !inputs.dry_run uses: actions/checkout@v7 with: ref: gh-pages path: pages continue-on-error: true - name: Update the repositories if: steps.key.outputs.present == 'yes' run: | # First release, or a dry run: there is no branch to start from. if [ ! -d pages/.git ]; then rm -rf pages && mkdir pages git -C pages init -q -b gh-pages git -C pages remote add origin "https://github.com/${{ github.repository }}.git" fi rm -f incoming/rpm-signer.asc packaging/publish-repos.sh pages incoming - name: Check that what was written can be verified if: steps.key.outputs.present == 'yes' run: | find pages -type f -not -path '*/.git/*' | sort echo '--- Release ---'; cat pages/deb/Release echo '--- Packages ---'; cat pages/deb/Packages gpg --verify pages/deb/InRelease gpg --verify pages/deb/Release.gpg pages/deb/Release gpg --verify pages/rpm/repodata/repomd.xml.asc pages/rpm/repodata/repomd.xml # The proof that the repository works is apt reading it: the signature, # the index, the dependencies and the program that comes out the far end. - name: Install from the repository that was just built if: inputs.dry_run run: | sudo install -d -m 0755 /etc/apt/keyrings sudo gpg --dearmor -o /etc/apt/keyrings/middleclick-autoscroll.gpg < pages/KEY.gpg echo "deb [signed-by=/etc/apt/keyrings/middleclick-autoscroll.gpg] file://$PWD/pages/deb ./" \ | sudo tee /etc/apt/sources.list.d/middleclick-autoscroll.list sudo apt-get update sudo apt-get install -y middleclick-autoscroll middleclick-autoscroll --version middleclick-autoscroll list - uses: actions/upload-artifact@v7 if: inputs.dry_run with: name: pages path: pages include-hidden-files: true - name: Push them if: steps.key.outputs.present == 'yes' && !inputs.dry_run env: GH_TOKEN: ${{ github.token }} run: | cd pages git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git add -A git diff --quiet --cached && { echo "nothing changed"; exit 0; } git commit -q -m "Publish ${{ github.ref_name }}" git push "https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git" HEAD:gh-pages verify-dnf: name: Install from the RPM repository needs: publish if: inputs.dry_run runs-on: ubuntu-latest container: fedora:latest steps: - uses: actions/download-artifact@v8 with: name: pages path: pages # A real run signs the package and the repository metadata with the one # key from the secret. A dry run has no secret, so each job made a key of # its own and both public halves are needed to check both signatures. - uses: actions/download-artifact@v8 with: name: rpm path: signer - name: Install from the repository that was just built run: | rpm --import pages/KEY.gpg rpm --import signer/rpm-signer.asc cat > /etc/yum.repos.d/middleclick-autoscroll.repo <