Files
site-publish/action.yaml
Evelyn ChenandClaude Fable 5.1 3dfee64335
Test / contract (pull_request) Successful in 7s
feat(site-publish): scope publication with an artifacts selection
A repository whose artifacts ship on different cadences has no way to
publish one of them. Baseline needs it: every merge to main must put the
catalogue live in under five minutes, while `dist/` is content-addressed
and may only be written by a tag release. Today the action iterates
cfg["artifacts"] unconditionally, so the only lever is deleting the
distributions artifact from site.yaml — which changes the stored
publication contract and drives the route-retirement path.

The new `artifacts:` input names the subset this run builds and
publishes. Selection scopes the build, the immutable preflight, the CORS
reconcile, the S3 sync, and credential resolution. It deliberately does
not scope manifest rendering or the immutable-path history: those stay
whole, so a scoped run can never retire another artifact's route or
delete its bucket contents. An undeclared name fails before the first
bucket is touched; `enabled: false` refuses a selection because
decommissioning is whole-site.

Default is unchanged: no input publishes every declared artifact.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjQqc4qFmdpAWaYfy2Aypb
2026-09-06 00:53:35 +00:00

73 lines
2.8 KiB
YAML

name: Publish Site
description: Build and deploy one or more routed static-content artifacts to Garage S3 with Traefik and cert-manager.
inputs:
token:
description: Gitea token (ci-bot) for apps repo push and API operations
required: true
s3-access-key:
description: Garage access key id (required by the legacy single-surface contract)
required: false
s3-secret-key:
description: Garage secret access key (required by the legacy single-surface contract)
required: false
s3-endpoint:
# Targets garage-s3 (data-only Service) so requests do not round-robin onto
# the gateway pod, whose emptyDir-backed metadata view intermittently
# returns "No such key" through the S3 API.
description: Garage S3 endpoint URL
required: false
default: http://garage-s3.storage.svc:3900
garage-admin-token:
description: Garage admin API token (required only for legacy aliases — used to reconcile bucket globalAliases)
required: false
garage-admin-endpoint:
description: Garage admin API endpoint URL
required: false
default: http://garage.storage.svc:3903
username:
description: Gitea username for git operations
required: false
default: ci-bot
artifacts:
# Scopes building and publishing only. Routes, Ingresses and the immutable
# -path history are always rendered from the whole site.yaml, so a scoped
# run never retires another artifact's route.
description: Space- or comma-separated subset of site.yaml artifacts to build and publish (default is every declared artifact)
required: false
default: ''
runs:
using: composite
steps:
- name: Setup
shell: bash
run: python3 ${{ github.action_path }}/scripts/setup.py
- name: Build
shell: bash
run: python3 ${{ github.action_path }}/scripts/publish.py build
env:
SITE_REPO: ${{ github.repository }}
SITE_DIR: ${{ github.workspace }}
ACTION_DIR: ${{ github.action_path }}
GITHUB_RUN_NUMBER: ${{ github.run_number }}
CI_BOT_USER: ${{ inputs.username }}
SITE_ARTIFACTS: ${{ inputs.artifacts }}
- name: Deploy
shell: bash
run: python3 ${{ github.action_path }}/scripts/publish.py deploy
env:
SITE_REPO: ${{ github.repository }}
SITE_DIR: ${{ github.workspace }}
ACTION_DIR: ${{ github.action_path }}
CI_BOT_TOKEN: ${{ inputs.token }}
CI_BOT_USER: ${{ inputs.username }}
AWS_ACCESS_KEY_ID: ${{ inputs.s3-access-key }}
AWS_SECRET_ACCESS_KEY: ${{ inputs.s3-secret-key }}
AWS_DEFAULT_REGION: sjc001
GARAGE_S3_ENDPOINT: ${{ inputs.s3-endpoint }}
GARAGE_ADMIN_ENDPOINT: ${{ inputs.garage-admin-endpoint }}
GARAGE_ADMIN_TOKEN: ${{ inputs.garage-admin-token }}
GITHUB_RUN_NUMBER: ${{ github.run_number }}
SITE_ARTIFACTS: ${{ inputs.artifacts }}