This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
# action/site-publish
|
||||
|
||||
Composite Gitea Action that publishes a **static-content** website to the
|
||||
fritzlab k8s cluster. Supports `static`, `hugo`, and `mkdocs`. Content goes
|
||||
to a Garage S3 bucket; Traefik fronts the bucket via an `ExternalName`
|
||||
Service with cert-manager TLS.
|
||||
Composite Gitea Action that publishes static content to the fritzlab cluster.
|
||||
The legacy form supports one `static`, `hugo`, or `mkdocs` output. The
|
||||
multi-artifact form publishes caller-built outputs to separate Garage buckets
|
||||
and gives each URL path its own cache, CORS, credential, and middleware
|
||||
boundary. Traefik fronts the buckets and cert-manager owns TLS.
|
||||
|
||||
> **Containerized web apps (Dockerfile-based) are NOT handled here.** Use the
|
||||
> standard image-producer chain instead:
|
||||
@@ -24,6 +25,11 @@ as a Garage `globalAlias` on the bucket and adds it to the Ingress + Certificate
|
||||
on every deploy. Manual edits to manifests in the apps repo are clobbered;
|
||||
edit `site.yaml` instead.
|
||||
|
||||
New sites with more than one security or caching boundary use the
|
||||
multi-artifact form below. An artifact is storage and release metadata. A
|
||||
route is edge behavior. Keeping them separate prevents a public path from
|
||||
inheriting the authenticated catalogue's cache or credentials.
|
||||
|
||||
## Usage
|
||||
|
||||
Scaffold a new site (handles repo creation + Garage bucket):
|
||||
@@ -55,6 +61,65 @@ type: static # static | hugo | mkdocs
|
||||
# # (also requires an Authentik proxy provider + app for the host).
|
||||
```
|
||||
|
||||
### Multiple artifacts on one host
|
||||
|
||||
Build each output before invoking the action, then declare the materialized
|
||||
directories and their routes:
|
||||
|
||||
```yaml
|
||||
domain: baseline.fritzlab.net
|
||||
artifacts:
|
||||
catalogue:
|
||||
source: apps/catalogue/build
|
||||
bucket: baseline-catalogue
|
||||
credential: catalogue
|
||||
cache:
|
||||
default: private, no-store
|
||||
dist:
|
||||
source: dist
|
||||
bucket: baseline-dist
|
||||
credential: dist
|
||||
cache:
|
||||
default: public, max-age=0, must-revalidate, no-transform
|
||||
rules:
|
||||
- match: releases/*
|
||||
value: public, max-age=31536000, immutable, no-transform
|
||||
cors_origins: ["*"]
|
||||
routes:
|
||||
- name: catalogue
|
||||
path: /
|
||||
artifact: catalogue
|
||||
access: protected
|
||||
- name: dist
|
||||
path: /dist
|
||||
artifact: dist
|
||||
access: public
|
||||
```
|
||||
|
||||
`source` is a repository-relative directory and cannot be the repository
|
||||
root. Every artifact needs an explicit, unique bucket and at least one route.
|
||||
Routes use Kubernetes `Prefix` matching. The route path becomes part of the
|
||||
published object key: `dist/baseline.css` is served at `/dist/baseline.css`.
|
||||
|
||||
`access` is required. Protected routes receive the organization Authentik
|
||||
middleware automatically and their artifacts must use `private` or `no-store`
|
||||
cache metadata. Public and protected routes cannot share an artifact. Cache
|
||||
rules use aws-cli include patterns in order after the default metadata pass;
|
||||
use immutable caching only for content-addressed or version-pinned paths.
|
||||
|
||||
The `default` credential profile uses the existing `AWS_ACCESS_KEY_ID` and
|
||||
`AWS_SECRET_ACCESS_KEY` inputs. A named profile such as `catalogue` reads
|
||||
`SITE_PUBLISH_CATALOGUE_S3_ACCESS_KEY_ID` and
|
||||
`SITE_PUBLISH_CATALOGUE_S3_SECRET_ACCESS_KEY` from the caller environment.
|
||||
Use a different Garage key for every security boundary. The action never logs
|
||||
credential values and clones the Apps repository without credentials in the
|
||||
remote URL.
|
||||
|
||||
Each artifact Service resolves through Garage's bucket virtual host and sets
|
||||
Traefik `passHostHeader` to false. The upstream therefore receives the bucket
|
||||
host while the browser retains the public host. This lets one DNS host address
|
||||
isolated Garage buckets without shared proxy configuration or CRDs.
|
||||
|
||||
`.gitea/workflows/publish.yaml`:
|
||||
|
||||
```yaml
|
||||
@@ -87,9 +152,9 @@ my-site.fritzlab.net 300 IN CNAME traefik.edge.svc.k8s.sjc001.fritzlab.net.
|
||||
| Input | Required | Default | Description |
|
||||
|---|---|---|---|
|
||||
| `token` | yes | | Gitea token for apps repo push |
|
||||
| `s3-access-key` | yes | | Garage `ci-deploy-key` access key id |
|
||||
| `s3-secret-key` | yes | | Garage `ci-deploy-key` secret key |
|
||||
| `s3-endpoint` | no | `http://garage.storage.svc:3900` | Garage S3 endpoint |
|
||||
| `s3-access-key` | only for the `default` profile | | Garage access key id |
|
||||
| `s3-secret-key` | only for the `default` profile | | Garage secret key |
|
||||
| `s3-endpoint` | no | `http://garage-s3.storage.svc:3900` | Garage S3 endpoint |
|
||||
| `garage-admin-token` | only if site has `aliases` | | Garage admin API token (`admin-token` from `garage-rpc-secret` in `storage` ns) |
|
||||
| `garage-admin-endpoint` | no | `http://garage.storage.svc:3903` | Garage admin API endpoint |
|
||||
| `username` | no | `ci-bot` | Gitea username |
|
||||
@@ -107,12 +172,12 @@ Org secrets in `websites`: `CI_BOT_TOKEN`, `GARAGE_S3_ACCESS_KEY`,
|
||||
```
|
||||
push to websites/<repo>
|
||||
→ CI runs site-publish action
|
||||
→ reads site.yaml, builds content (static copy / hugo / mkdocs), runs tidy
|
||||
→ aws s3 sync → Garage bucket named after the repo
|
||||
→ reads site.yaml and either builds legacy content or snapshots caller-built artifacts
|
||||
→ aws s3 sync → one Garage bucket per artifact, with isolated credentials and metadata
|
||||
→ admin API: ensures every alias from site.yaml is a globalAlias on the bucket
|
||||
→ renders manifests in fritzlab/apps from templates: ExternalName Service →
|
||||
garage.storage.svc, Traefik Ingress (canonical + aliases), cert-manager
|
||||
Certificate (canonical + aliases as SANs), kustomization
|
||||
→ renders manifests in fritzlab/apps from templates: ExternalName Services →
|
||||
Garage bucket virtual hosts, path-scoped Traefik Ingresses,
|
||||
cert-manager Certificate (canonical + aliases as SANs), kustomization
|
||||
→ commits + pushes apps repo only if diff is non-empty
|
||||
→ ArgoCD syncs → site live with TLS
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user