265 lines
9.2 KiB
YAML
265 lines
9.2 KiB
YAML
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 }}"
|
|
|
|
- name: Check CHANGELOG.md has this release
|
|
if: startsWith(github.ref, 'refs/tags/v')
|
|
run: .github/release-notes.sh --title "${{ 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 <dry-run@example.invalid>' 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
|
|
with:
|
|
# All tags, for the link to the changes since the last release.
|
|
fetch-depth: 0
|
|
|
|
- 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: |
|
|
.github/release-notes.sh "${{ github.ref_name }}" > notes.md
|
|
gh release create "${{ github.ref_name }}" \
|
|
--title "$(.github/release-notes.sh --title "${{ github.ref_name }}")" \
|
|
--notes-file notes.md \
|
|
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 <dry-run@example.invalid>' 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, so 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 <<EOF
|
|
[middleclick-autoscroll]
|
|
name=middleclick-autoscroll
|
|
baseurl=file://$PWD/pages/rpm
|
|
enabled=1
|
|
gpgcheck=1
|
|
repo_gpgcheck=1
|
|
gpgkey=file://$PWD/pages/KEY.gpg
|
|
EOF
|
|
# util-linux is for runuser below; the base image does not carry it,
|
|
# and util-linux-core is not the half that has it.
|
|
dnf install -y middleclick-autoscroll util-linux
|
|
|
|
# As somebody, not as root: running it as root is refused, which is
|
|
# the point of it, and a container is root by default.
|
|
useradd -m tester
|
|
runuser -u tester -- middleclick-autoscroll --version
|
|
runuser -u tester -- middleclick-autoscroll list
|