Files
jasp-desktop-bin/.gitea/workflows/build.yml
T
agw aa08dc108e Keep infrastructure details out of the repository
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
2026-10-01 17:05:00 +02:00

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