--- name: Update RPM Packages on: schedule: - cron: "0 0 * * *" workflow_dispatch: inputs: package: description: "Single package to update (blank = all)" required: false type: string force_rebuild: description: "Bump the Release even with no new upstream version" required: false type: boolean default: false force_refresh: description: "Re-download the source and rebuild even when nothing changed" required: false type: boolean default: false no_git_push: description: "Dry run: build, but neither upload nor push" required: false type: boolean default: false defaults: run: shell: bash jobs: update: runs-on: ubuntu-latest # rpmbuild runs as the unprivileged `builder` user inside a Fedora image; # the spec is built with `dist` undefined, so the noarch package is the # same for every RPM distribution the registry serves. # # Prebuilt by build-image.yaml (see dockerfile) so the toolchain is not # reinstalled in every job every night. container: image: git.bjphoster.com/rpm/autoupdate:latest credentials: username: ${{ vars.REGISTRY_USER }} password: ${{ secrets.GIT_TOKEN }} strategy: # One broken package must not cancel the rest of the matrix. fail-fast: false matrix: package: - skeptical-updater steps: # No bootstrap step: node, git, jq, curl and the packaging toolchain all # come from the prebuilt image above. node in particular has to be present # before this action runs, since actions/checkout is JavaScript and the # runner executes it with `node` from the image. - uses: actions/checkout@v4 # The same credential serves git (clone/push of the package repos) and # the package registry upload, which autoupdate.sh reads back through # `git credential fill`. GIT_TOKEN therefore needs write:repository AND # write:package. - name: Configure git env: GIT_NAME: ${{ vars.GIT_NAME }} GIT_EMAIL: ${{ vars.GIT_EMAIL }} GIT_HOST: ${{ vars.GIT_HOST || 'git.bjphoster.com' }} GIT_TOKEN: ${{ secrets.GIT_TOKEN }} run: | set -euo pipefail # Validate HERE rather than letting a missing secret surface as an # opaque 401 several steps later. for v in GIT_NAME GIT_EMAIL GIT_TOKEN; do if [ -z "${!v//[[:space:]]/}" ]; then echo "::error::${v} is empty or unset (see README: required secrets and variables)" >&2 exit 1 fi done git config --global user.name "${GIT_NAME}" git config --global user.email "${GIT_EMAIL}" git config --global credential.helper store echo "https://${GIT_EMAIL//@/%40}:${GIT_TOKEN}@${GIT_HOST}" > ~/.git-credentials chmod 600 ~/.git-credentials # The `builder` user is baked into the image; this only hands it the # workspace and the credentials written by the previous step. - name: Hand over to the build user run: | set -euo pipefail chown -R builder:builder "${GITHUB_WORKSPACE}" cp /root/.gitconfig /root/.git-credentials /home/builder/ chown -R builder:builder /home/builder - name: Update ${{ matrix.package }} env: GIT_HOST: ${{ vars.GIT_HOST || 'git.bjphoster.com' }} # Compared against both `true` and 'true' on purpose. A bare # `${{ inputs.x && '1' || '' }}` is wrong if the runner hands the # input over as the STRING "false", which is truthy -- that would # silently enable the flag on every run. FORCE_REBUILD: ${{ (inputs.force_rebuild == true || inputs.force_rebuild == 'true') && '1' || '' }} FORCE_REFRESH: ${{ (inputs.force_refresh == true || inputs.force_refresh == 'true') && '1' || '' }} NO_GIT_PUSH: ${{ (inputs.no_git_push == true || inputs.no_git_push == 'true') && '1' || '' }} run: | set -euo pipefail # workflow_dispatch with a package name runs only that one. want="${{ inputs.package }}" if [ -n "${want}" ] && [ "${want}" != "${{ matrix.package }}" ]; then echo "skipping ${{ matrix.package }} (dispatch asked for ${want})" exit 0 fi runuser -u builder -- env \ GIT_HOST="${GIT_HOST}" \ FORCE_REBUILD="${FORCE_REBUILD}" \ FORCE_REFRESH="${FORCE_REFRESH}" \ NO_GIT_PUSH="${NO_GIT_PUSH}" \ ./autoupdate.sh "${{ matrix.package }}"