The README, the publish script and the workflow named the tarball host, its
address and filesystem paths on the web host and the runner. Hosts and paths
now come only from repository variables, and the workflow shares the work
tree and the build cache through the named Docker volumes jasp-build and
jasp-cache instead of host paths. (The runner does not expand ${{ vars }} in
container.volumes, so a variable could not have replaced the host path there.)
Also drop the unused scripts/gen-tarball-index.py, and give each module build
its own process under a time limit: a module once spun for eight hours in
jaspModuleTools' bundling step and stalled the whole build.
Claude-Session: https://claude.ai/code/session_01GGe7kUhooMFuzY6GaDb2w9
191 lines
6.7 KiB
YAML
191 lines
6.7 KiB
YAML
name: Build JASP binary and publish to AUR
|
|
|
|
# JASP publishes no Linux binary of its own, so this builds one on Arch and
|
|
# ships it as jasp-desktop-bin. Because JASP links against the system R and Qt6,
|
|
# a rebuild is needed both when JASP releases and when Arch bumps R or Qt6 —
|
|
# check-upstream.py decides which.
|
|
|
|
on:
|
|
schedule:
|
|
# 16:00 UTC is 18:00 CEST / 17:00 CET. A full build takes a little over two
|
|
# hours, so the AUR push (made under the maintainer's name) and the
|
|
# state.json commit land on an evening, not in working hours.
|
|
- cron: '0 16 * * *'
|
|
workflow_dispatch:
|
|
inputs:
|
|
jasp_tag:
|
|
description: 'Specific JASP tag to build (blank = latest release)'
|
|
required: false
|
|
default: ''
|
|
force:
|
|
description: 'Build even if nothing changed'
|
|
type: boolean
|
|
default: false
|
|
|
|
concurrency:
|
|
group: jasp-build
|
|
cancel-in-progress: false
|
|
|
|
# Nothing leaves the runner unless the repo variable PUBLISH is 'true'. Without
|
|
# it a run builds, verifies and generates the PKGBUILD, and leaves the tarball
|
|
# in ${WORK_DIR}/out for inspection: a dry run that cannot touch the tarball
|
|
# host, state.json or the AUR.
|
|
env:
|
|
AUR_MAINTAINER: ${{ vars.AUR_MAINTAINER }}
|
|
TARBALL_HOST: ${{ vars.TARBALL_HOST }}
|
|
TARBALL_PATH: ${{ vars.TARBALL_PATH }}
|
|
TARBALL_BASE_URL: ${{ vars.TARBALL_BASE_URL }}
|
|
WORK_DIR: /work
|
|
|
|
jobs:
|
|
check:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
needs_build: ${{ steps.decide.outputs.needs_build }}
|
|
jasp_tag: ${{ steps.decide.outputs.jasp_tag }}
|
|
reasons: ${{ steps.decide.outputs.reasons }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Decide whether a rebuild is needed
|
|
id: decide
|
|
env:
|
|
JASP_TAG: ${{ inputs.jasp_tag }}
|
|
FORCE_BUILD: ${{ inputs.force }}
|
|
run: python3 scripts/check-upstream.py
|
|
|
|
build:
|
|
needs: check
|
|
if: needs.check.outputs.needs_build == 'true'
|
|
runs-on: ubuntu-latest
|
|
# The R module tree is several hundred packages compiled from source; the
|
|
# full build runs for hours. The act_runner timeout and Gitea's
|
|
# ENDLESS_TASK_TIMEOUT must both allow for this (see README).
|
|
timeout-minutes: 900
|
|
# The build step's `docker run` talks to the runner's docker daemon, not to
|
|
# this job container, so the two only share files through a Docker volume.
|
|
# Without it the scripts prepared here never reach the build and the
|
|
# tarball the build writes is invisible to the publish steps. Named volumes
|
|
# rather than host paths: the runner does not expand ${{ vars }} in
|
|
# container.volumes, and a host path would put runner internals in the repo.
|
|
container:
|
|
image: docker.gitea.com/runner-images:ubuntu-latest
|
|
volumes:
|
|
- jasp-build:/work
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Report plan
|
|
run: |
|
|
echo "Building JASP ${{ needs.check.outputs.jasp_tag }}"
|
|
echo "Reasons: ${{ needs.check.outputs.reasons }}"
|
|
|
|
- name: Prepare work directory
|
|
run: |
|
|
# WORK_DIR is a volume mount point, so empty it rather than removing it.
|
|
sudo find "${WORK_DIR}" -mindepth 1 -delete
|
|
sudo mkdir -p "${WORK_DIR}/out"
|
|
sudo cp -a build packaging scripts "${WORK_DIR}/"
|
|
df -h /
|
|
|
|
- name: Build JASP in an Arch container
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
|
run: |
|
|
docker rm -f jasp-build 2>/dev/null || true
|
|
docker run --rm --name jasp-build \
|
|
-v jasp-build:/work \
|
|
-v jasp-cache:/cache \
|
|
-e JASP_TAG="${{ needs.check.outputs.jasp_tag }}" \
|
|
-e OUT_DIR=/work/out \
|
|
-e JOBS=5 \
|
|
-e GITHUB_PAT="${GH_TOKEN}" \
|
|
archlinux:base-devel \
|
|
bash /work/build/build-jasp.sh
|
|
|
|
- name: Show build result
|
|
run: |
|
|
cat "${WORK_DIR}/out/build-info.json"
|
|
ls -lh "${WORK_DIR}/out/"
|
|
|
|
- name: Generate PKGBUILD
|
|
run: |
|
|
sudo cp "${WORK_DIR}/out/build-info.json" .
|
|
python3 scripts/gen-pkgbuild.py \
|
|
--build-info build-info.json \
|
|
--template packaging/PKGBUILD.in \
|
|
--out PKGBUILD \
|
|
--base-url "${TARBALL_BASE_URL}" \
|
|
--maintainer "${AUR_MAINTAINER}"
|
|
cat PKGBUILD
|
|
|
|
# Must run before the AUR push: the PKGBUILD's sha256sum refers to this
|
|
# file, so publishing the package before the tarball exists would leave
|
|
# users with a 404.
|
|
- name: Publish tarball to asger.weirsoe.dk
|
|
if: vars.PUBLISH == 'true'
|
|
env:
|
|
TARBALL_SSH_KEY: ${{ secrets.TARBALL_SSH_KEY }}
|
|
run: |
|
|
ASSET="$(python3 -c 'import json;print(json.load(open("release-meta.json"))["tarball"])')"
|
|
bash scripts/publish-tarball.sh "${WORK_DIR}/out/${ASSET}"
|
|
|
|
- name: Verify the published URL actually serves the tarball
|
|
if: vars.PUBLISH == 'true'
|
|
run: |
|
|
URL="$(python3 -c 'import json;print(json.load(open("release-meta.json"))["download_url"])')"
|
|
WANT="$(python3 -c 'import json;print(json.load(open("release-meta.json"))["sha256"])')"
|
|
echo "checking $URL"
|
|
GOT="$(curl -fsSL --retry 3 "$URL" | sha256sum | awk '{print $1}')"
|
|
if [ "$GOT" != "$WANT" ]; then
|
|
echo "error: what the public URL serves does not match the PKGBUILD sha256" >&2
|
|
echo " want $WANT" >&2
|
|
echo " got $GOT" >&2
|
|
exit 1
|
|
fi
|
|
echo "public URL serves the expected bytes"
|
|
|
|
# Only the PKGBUILD and metadata cross the job boundary — the tarball
|
|
# itself already lives on GitHub Releases.
|
|
- name: Hand PKGBUILD to the AUR job
|
|
if: vars.PUBLISH == 'true'
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: aur-package
|
|
path: |
|
|
PKGBUILD
|
|
release-meta.json
|
|
|
|
- name: Record built state
|
|
if: vars.PUBLISH == 'true'
|
|
env:
|
|
STATE_PUSH_TOKEN: ${{ secrets.STATE_PUSH_TOKEN }}
|
|
run: bash scripts/record-state.sh
|
|
|
|
- name: Clean up build tree
|
|
if: always()
|
|
run: |
|
|
sudo rm -rf "${WORK_DIR}/jasp-desktop" "${WORK_DIR}/build" "${WORK_DIR}/stage" || true
|
|
df -h /
|
|
|
|
aur:
|
|
needs: [check, build]
|
|
if: vars.PUBLISH == 'true'
|
|
runs-on: ubuntu-latest
|
|
container:
|
|
image: archlinux:base-devel
|
|
steps:
|
|
- name: Install base tools
|
|
run: pacman -Syu --noconfirm git openssh pacman-contrib nodejs sudo
|
|
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/download-artifact@v3
|
|
with:
|
|
name: aur-package
|
|
|
|
- name: Push to AUR
|
|
env:
|
|
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
|
run: bash scripts/push-aur.sh PKGBUILD
|