Skip to content

Publish addons

Publish addons #21

name: Publish addons
on:
workflow_dispatch:
inputs:
addon:
description: One addon directory name, or "all"
default: all
staging:
description: Publish under staging/ instead of the live keys
type: boolean
default: true
# This job holds the R2 write credentials and runs Gradle builds for every
# addon directory, so its token gets the least it can do its work with.
permissions:
contents: read
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
- uses: gradle/actions/setup-gradle@v4
- uses: astral-sh/setup-uv@v5
- name: Verify the R2 configuration
# The build below takes a long time. Without this, a renamed variable
# is only discovered after all of it, inside boto3.
env:
R2_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
R2_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_ACCESS_KEY_ID }}
R2_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_SECRET_ACCESS_KEY }}
R2_BUCKET: ${{ vars.CLOUDFLARE_R2_BUCKET_NAME }}
run: |
for v in R2_ACCOUNT_ID R2_ACCESS_KEY_ID R2_SECRET_ACCESS_KEY R2_BUCKET; do
if [ -z "${!v}" ]; then
echo "$v is empty. Check the repository secrets and variables." >&2
exit 1
fi
done
echo "Publishing to bucket '$R2_BUCKET'."
- name: Check names and metadata
run: uv run --directory tools/addons addons --root "$GITHUB_WORKSPACE" check
- name: Fetch plugin-api-latest from CodeOnTheGo
id: libs
env:
GH_TOKEN: ${{ github.token }}
COGO_REPO: appdevforall/CodeOnTheGo
COGO_RELEASE: plugin-api-latest
run: |
set -euo pipefail
target() { gh release view "$COGO_RELEASE" -R "$COGO_REPO" --json targetCommitish -q .targetCommitish; }
before="$(target)"
if ! [[ "$before" =~ ^[0-9a-f]{40}$ ]]; then
echo "$COGO_RELEASE targets '$before', not a commit sha." >&2
exit 1
fi
fetched="$(mktemp -d)"
gh release download "$COGO_RELEASE" -R "$COGO_REPO" -D "$fetched" \
-p plugin-api.jar -p gradle-plugin.jar -p checksums.txt
( cd "$fetched" && sha256sum --check --strict checksums.txt )
after="$(target)"
if [ "$before" != "$after" ]; then
echo "$COGO_RELEASE was republished during the download ($before -> $after). Re-run." >&2
exit 1
fi
cp "$fetched/plugin-api.jar" "$fetched/gradle-plugin.jar" libs/
revision="${before:0:12}"
echo "revision=$revision" >> "$GITHUB_OUTPUT"
echo "Building against $COGO_REPO@$revision ($COGO_RELEASE)." >> "$GITHUB_STEP_SUMMARY"
- name: Build, package, and stage
id: stage
env:
ADDON: ${{ inputs.addon }}
PLUGIN_LIBS_REVISION: ${{ steps.libs.outputs.revision }}
run: |
set -euo pipefail
# Without a name, discover lists every addon not held back by skip.txt.
# With one, it resolves the directory name or the slug, in any case, and
# fails on an unknown one, so a hostile value never reaches the shell as
# a path.
if [ "$ADDON" = "all" ]; then
names="$(uv run --directory tools/addons addons --root "$GITHUB_WORKSPACE" discover)"
else
names="$(uv run --directory tools/addons addons --root "$GITHUB_WORKSPACE" discover "$ADDON")"
fi
printf 'only<<EOF\n%s\nEOF\n' "$names" >> "$GITHUB_OUTPUT"
# Two kinds of addon, two build scripts (ADFA-6252). Each builds only its
# own kind from the list and ignores the rest. No --ref: the previous
# step already put the plugin-api-latest jars in libs/.
# shellcheck disable=SC2086
./scripts/build-plugins.sh --out dist $names
# shellcheck disable=SC2086
./scripts/build-templates.sh $names
- name: Build the source tarballs
env:
ONLY: ${{ steps.stage.outputs.only }}
run: |
# Templates are passed in with everything else and skipped inside the
# tool, which logs the skip: a template ships no source tarball because
# its .cgt is plain text and already is its source (ADFA-6252). Filtering
# here instead would put the rule in two places.
# shellcheck disable=SC2086
uv run --directory tools/addons addons --root "$GITHUB_WORKSPACE" \
tarball --out "$GITHUB_WORKSPACE/dist" --only $ONLY
- name: Work out where this is being published
id: dest
env:
STAGING: ${{ inputs.staging }}
run: |
prefix=""
if [ "$STAGING" = "true" ]; then
prefix="staging/${{ github.run_id }}/"
fi
echo "prefix=${prefix}" >> "$GITHUB_OUTPUT"
base="https://addons.appdevforall.org${prefix:+/${prefix%/}}"
echo "base=$base" >> "$GITHUB_OUTPUT"
- name: Generate the catalog
env:
BASE: ${{ steps.dest.outputs.base }}
ONLY: ${{ steps.stage.outputs.only }}
ADDONS_SOURCE_REF: ${{ github.ref_name }}
run: |
# shellcheck disable=SC2086
uv run --directory tools/addons addons --root "$GITHUB_WORKSPACE" catalog \
--dist "$GITHUB_WORKSPACE/dist" \
--out "$GITHUB_WORKSPACE/dist/catalog.json" \
--base "$BASE" --only $ONLY
- name: Publish to Cloudflare R2
env:
R2_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
R2_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_ACCESS_KEY_ID }}
R2_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_SECRET_ACCESS_KEY }}
R2_BUCKET: ${{ vars.CLOUDFLARE_R2_BUCKET_NAME }}
PREFIX: ${{ steps.dest.outputs.prefix }}
BASE: ${{ steps.dest.outputs.base }}
ONLY: ${{ steps.stage.outputs.only }}
run: |
# shellcheck disable=SC2086
uv run --directory tools/addons addons --root "$GITHUB_WORKSPACE" publish \
--dist "$GITHUB_WORKSPACE/dist" --prefix "$PREFIX" --only $ONLY
{
echo "### Published"
echo "$BASE/index.html"
} >> "$GITHUB_STEP_SUMMARY"