@cleocode/cleo 2026.5.77 → 2026.5.79
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +3005 -918
- package/dist/cli/index.js.map +3 -3
- package/package.json +11 -10
- package/templates/workflows/README.md +157 -0
- package/templates/workflows/release-fanout.yml.tmpl +214 -0
- package/templates/workflows/release-prepare.yml.tmpl +296 -0
- package/templates/workflows/release-publish.yml.tmpl +388 -0
- package/templates/workflows/release-rollback.yml.tmpl +322 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cleocode/cleo",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.79",
|
|
4
4
|
"description": "CLEO CLI — the assembled product consuming @cleocode/core",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cli/index.js",
|
|
@@ -29,17 +29,18 @@
|
|
|
29
29
|
"tree-sitter-ruby": "^0.23.1",
|
|
30
30
|
"tree-sitter-rust": "0.23.1",
|
|
31
31
|
"tree-sitter-typescript": "^0.23.2",
|
|
32
|
-
"@cleocode/
|
|
33
|
-
"@cleocode/
|
|
34
|
-
"@cleocode/
|
|
35
|
-
"@cleocode/
|
|
36
|
-
"@cleocode/
|
|
37
|
-
"@cleocode/nexus": "2026.5.
|
|
38
|
-
"@cleocode/
|
|
39
|
-
"@cleocode/
|
|
32
|
+
"@cleocode/animations": "2026.5.79",
|
|
33
|
+
"@cleocode/caamp": "2026.5.79",
|
|
34
|
+
"@cleocode/contracts": "2026.5.79",
|
|
35
|
+
"@cleocode/lafs": "2026.5.79",
|
|
36
|
+
"@cleocode/cant": "2026.5.79",
|
|
37
|
+
"@cleocode/nexus": "2026.5.79",
|
|
38
|
+
"@cleocode/paths": "2026.5.79",
|
|
39
|
+
"@cleocode/playbooks": "2026.5.79",
|
|
40
|
+
"@cleocode/runtime": "2026.5.79"
|
|
40
41
|
},
|
|
41
42
|
"peerDependencies": {
|
|
42
|
-
"@cleocode/core": "2026.5.
|
|
43
|
+
"@cleocode/core": "2026.5.79"
|
|
43
44
|
},
|
|
44
45
|
"peerDependenciesMeta": {
|
|
45
46
|
"@cleocode/core": {
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# CLEO GitHub Actions workflow templates
|
|
2
|
+
|
|
3
|
+
This directory contains CLEO's templated GitHub Actions workflows for the
|
|
4
|
+
release pipeline defined in
|
|
5
|
+
`.cleo/rcasd/T9345/research/SPEC-T9345-release-pipeline-v2.md`. Templates
|
|
6
|
+
are project-agnostic: they ship with `{{PLACEHOLDER}}` markers that are
|
|
7
|
+
resolved at scaffold time by `cleo init --workflows` (T9531) against the
|
|
8
|
+
local `.cleo/project-context.json` and the ADR-061 tool resolver.
|
|
9
|
+
|
|
10
|
+
## Template files
|
|
11
|
+
|
|
12
|
+
| Template | SPEC section | Purpose |
|
|
13
|
+
|-----------------------------------|--------------|--------------------------------------------------------|
|
|
14
|
+
| `release-prepare.yml.tmpl` | §5.1 | Cut release branch, bump version, open bump-PR. |
|
|
15
|
+
| `release-publish.yml.tmpl` | §5.2 | Publish + tag once the bump-PR is merged. |
|
|
16
|
+
| `release-fanout.yml.tmpl` | §5.3 | Best-effort post-publish fanout (docs, docker, etc.). |
|
|
17
|
+
| `release-rollback.yml.tmpl` | §5.4 | Rollback workflow (revert PR + npm deprecate + reconcile). |
|
|
18
|
+
|
|
19
|
+
## Template contract
|
|
20
|
+
|
|
21
|
+
- Templates MUST use `{{PLACEHOLDER}}` markers compatible with simple regex
|
|
22
|
+
substitution (`s/{{NAME}}/value/g`). They MUST NOT use Mustache, Handlebars,
|
|
23
|
+
or any nested-syntax templating engine — the scaffold step relies on
|
|
24
|
+
deterministic, single-pass regex replacement so a stale template can be
|
|
25
|
+
diffed cleanly against a re-render.
|
|
26
|
+
- Placeholder names MUST be `UPPER_SNAKE_CASE` wrapped in double braces.
|
|
27
|
+
- Templates MUST be ASCII-only outside of strings.
|
|
28
|
+
- Templates MUST pass `actionlint` after substitution. The
|
|
29
|
+
`release-prepare-render.test.ts` snapshot test renders with sample values
|
|
30
|
+
and (if `actionlint` is on `PATH`) pipes the output through `actionlint -`
|
|
31
|
+
via `child_process.execSync`.
|
|
32
|
+
|
|
33
|
+
## Placeholders
|
|
34
|
+
|
|
35
|
+
All four templates draw from the same placeholder vocabulary. Unused
|
|
36
|
+
placeholders for a given template are silently ignored by the scaffolder.
|
|
37
|
+
|
|
38
|
+
| Placeholder | Source | Default | Example |
|
|
39
|
+
|-----------------------|--------------------------------------------------------|--------------------------------------|--------------------------------------|
|
|
40
|
+
| `{{NODE_VERSION}}` | `.cleo/project-context.json` `node.version` | `22.x` | `"22.x"` |
|
|
41
|
+
| `{{INSTALL_CMD}}` | ADR-061 archetype defaults (`primaryType`-specific) | `pnpm install --frozen-lockfile` | `pnpm install --frozen-lockfile` |
|
|
42
|
+
| `{{LINT_CMD}}` | ADR-061 `tool:lint` resolution | `pnpm run lint` | `pnpm biome ci .` |
|
|
43
|
+
| `{{TYPECHECK_CMD}}` | ADR-061 `tool:typecheck` resolution | `pnpm run typecheck` | `pnpm run typecheck` |
|
|
44
|
+
| `{{TEST_CMD}}` | ADR-061 `tool:test` resolution | `pnpm run test` | `pnpm run test` |
|
|
45
|
+
| `{{BUILD_CMD}}` | ADR-061 `tool:build` resolution | `pnpm run build` | `pnpm run build` |
|
|
46
|
+
| `{{BRANCH_PREFIX}}` | `release.branchPrefix` in `.cleo/config.json` | `release` | `release` |
|
|
47
|
+
| `{{PR_LABEL}}` | `release.prLabel` in `.cleo/config.json` | `release` | `release` |
|
|
48
|
+
| `{{NPM_PUBLISH_CMD}}` | `release.npmPublishCmd` in `.cleo/config.json` | `pnpm publish --access public --tag latest` | `pnpm publish -r --access public --tag latest` |
|
|
49
|
+
| `{{PUBLISHERS}}` | `release.publishers` in `.cleo/config.json` | `npm` | `npm cargo` |
|
|
50
|
+
| `{{DOCS_BUILD_CMD}}` | `release.fanout.docsBuildCmd` in `.cleo/config.json` | `pnpm run docs:build` | `pnpm --filter @cleocode/docs run build` |
|
|
51
|
+
| `{{ENABLE_DOCS_DEPLOY}}` | `release.fanout.docsDeploy` in `.cleo/config.json` | `false` | `true` |
|
|
52
|
+
| `{{ENABLE_DOCKER_RETAG}}` | `release.fanout.dockerRetag` in `.cleo/config.json` | `false` | `true` |
|
|
53
|
+
| `{{ENABLE_SENTINEL_NOTIFY}}` | `release.fanout.sentinelNotify` in `.cleo/config.json` | `false` | `true` |
|
|
54
|
+
| `{{ENABLE_STUDIO_DEPLOY}}` | `release.fanout.studioDeploy` in `.cleo/config.json` | `false` | `true` |
|
|
55
|
+
| `{{ENABLE_NIGHTLY_TRIGGER}}` | `release.fanout.nightlyTrigger` in `.cleo/config.json` | `false` | `true` |
|
|
56
|
+
| `{{DOCKER_IMAGE}}` | `release.fanout.dockerImage` in `.cleo/config.json` | *(none — required if `dockerRetag=true`)* | `cleocode/cleo` |
|
|
57
|
+
| `{{DOCKER_HUB_USER}}` | `release.fanout.dockerHubUser` in `.cleo/config.json` | *(none — required if `dockerRetag=true`)* | `cleocode` |
|
|
58
|
+
| `{{SENTINEL_WEBHOOK_URL}}` | `release.fanout.sentinelWebhookUrl` in `.cleo/config.json` | *(none — required if `sentinelNotify=true`)* | `https://sentinel.example.com/hooks/release` |
|
|
59
|
+
| `{{STUDIO_DEPLOY_HOOK}}` | `release.fanout.studioDeployHook` in `.cleo/config.json` | *(none — required if `studioDeploy=true`)* | `https://studio.example.com/deploy` |
|
|
60
|
+
| `{{NPM_PACKAGES}}` | `release.rollback.npmPackages` in `.cleo/config.json` | *(none — required if `PUBLISHERS` contains `npm`)* | `@cleocode/cleo @cleocode/core` |
|
|
61
|
+
| `{{CARGO_CRATES}}` | `release.rollback.cargoCrates` in `.cleo/config.json` | *(none — required if `PUBLISHERS` contains `cargo`)* | `cleo-core cleo-cli` |
|
|
62
|
+
|
|
63
|
+
Source precedence (highest first):
|
|
64
|
+
|
|
65
|
+
1. Explicit override in `.cleo/project-context.json` (ADR-061 §1).
|
|
66
|
+
2. Project archetype default keyed on `primaryType` (e.g. `node` → `pnpm`,
|
|
67
|
+
`rust` → `cargo`, `python` → `uv`).
|
|
68
|
+
3. Hard-coded fallback in the scaffolder.
|
|
69
|
+
|
|
70
|
+
## GitHub permissions required per template
|
|
71
|
+
|
|
72
|
+
| Template | `contents` | `pull-requests` | `id-token` | `packages` | Other |
|
|
73
|
+
|------------------------------|-----------------|------------------|----------------------|--------------------|------------------|
|
|
74
|
+
| `release-prepare.yml.tmpl` | `write` | `write` | `write` (signed tags) | (MUST NOT request) | — |
|
|
75
|
+
| `release-publish.yml.tmpl` | `write` (tag) | `read` | `write` (OIDC) | `write` (publish job only) | — |
|
|
76
|
+
| `release-fanout.yml.tmpl` | `read` | — | `write` (Pages, docs job only)* | — | `pages: write`* |
|
|
77
|
+
| `release-rollback.yml.tmpl` | `write` (revert + tag delete) | `write` | — | `write` (npm deprecate) | — |
|
|
78
|
+
|
|
79
|
+
*Per-job — only granted to the job that needs it.
|
|
80
|
+
|
|
81
|
+
## Required secrets
|
|
82
|
+
|
|
83
|
+
| Template | Required secrets | Optional secrets |
|
|
84
|
+
|------------------------------|-------------------------|---------------------------------------------------|
|
|
85
|
+
| `release-prepare.yml.tmpl` | `GITHUB_TOKEN` (auto) | *(none)* — MUST NOT require `NPM_TOKEN` (R-210) |
|
|
86
|
+
| `release-publish.yml.tmpl` | `GITHUB_TOKEN`, `NPM_TOKEN`, `ANTHROPIC_API_KEY` | `CARGO_TOKEN`, `PYPI_TOKEN`, `DOCKER_HUB_TOKEN` |
|
|
87
|
+
| `release-fanout.yml.tmpl` | `GITHUB_TOKEN` (auto) | `DOCKER_HUB_TOKEN` (if `dockerRetag=true`), `SENTINEL_TOKEN` (if `sentinelNotify=true`), `STUDIO_DEPLOY_TOKEN` (if `studioDeploy=true`) |
|
|
88
|
+
| `release-rollback.yml.tmpl` | `GITHUB_TOKEN` (auto), `NPM_TOKEN` (if `PUBLISHERS` contains `npm`) | `CARGO_TOKEN` (if `PUBLISHERS` contains `cargo`) |
|
|
89
|
+
|
|
90
|
+
## Scaffolding workflow
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Render the templates against the local project, writing to .github/workflows/.
|
|
94
|
+
cleo init --workflows
|
|
95
|
+
|
|
96
|
+
# Re-render after editing project-context.json or release config.
|
|
97
|
+
cleo init --workflows --force
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The scaffolder reads each `*.yml.tmpl` file in this directory, performs
|
|
101
|
+
regex substitution against the placeholder vocabulary above, validates the
|
|
102
|
+
result with `actionlint`, and writes the rendered YAML to
|
|
103
|
+
`<project>/.github/workflows/<basename>.yml`. Existing files are NOT
|
|
104
|
+
overwritten without `--force`.
|
|
105
|
+
|
|
106
|
+
## Extending without forking
|
|
107
|
+
|
|
108
|
+
Per SPEC R-260, downstream projects MAY layer customizations onto the
|
|
109
|
+
rendered workflows via a sibling `.github/workflows/<basename>.overrides.yml`
|
|
110
|
+
file (planned: `.workflow-overrides.yml` at repo root for cross-template
|
|
111
|
+
overrides). The scaffolder merges overrides as a final pass; conflicts at
|
|
112
|
+
the same YAML key path resolve to the override.
|
|
113
|
+
|
|
114
|
+
Override examples (illustrative — full schema lands with T9531):
|
|
115
|
+
|
|
116
|
+
```yaml
|
|
117
|
+
# .github/workflows/release-prepare.overrides.yml
|
|
118
|
+
jobs:
|
|
119
|
+
preflight:
|
|
120
|
+
steps:
|
|
121
|
+
- name: Project-specific cache warm
|
|
122
|
+
run: ./scripts/warm-cache.sh
|
|
123
|
+
timeout-minutes: 3
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Overrides MUST NOT remove or relax any RFC2119 invariant from
|
|
127
|
+
`SPEC-T9345-release-pipeline-v2.md`. The scaffolder rejects override files
|
|
128
|
+
that drop required `timeout-minutes`, modify `concurrency.group`, or strip
|
|
129
|
+
declared permissions.
|
|
130
|
+
|
|
131
|
+
## Cross-references
|
|
132
|
+
|
|
133
|
+
- SPEC: `.cleo/rcasd/T9345/research/SPEC-T9345-release-pipeline-v2.md`
|
|
134
|
+
- §5.1 → `release-prepare.yml.tmpl` *(T9532, landed)*
|
|
135
|
+
- §5.2 → `release-publish.yml.tmpl` *(T9533, landed)*
|
|
136
|
+
- §5.3 → `release-fanout.yml.tmpl` *(T9534, landed)*
|
|
137
|
+
- §5.4 → `release-rollback.yml.tmpl` *(T9535, current)*
|
|
138
|
+
- ADR-061 (tool resolver): governs `tool:*` placeholder resolution.
|
|
139
|
+
- ADR-073 (release pipeline v2): umbrella architectural decision.
|
|
140
|
+
- T9531: `cleo init --workflows` scaffold command (consumes these templates).
|
|
141
|
+
- T9532: `release-prepare.yml.tmpl` + README skeleton + snapshot test.
|
|
142
|
+
- T9533: `release-publish.yml.tmpl` + README placeholders + snapshot test
|
|
143
|
+
(eliminates F6 tag-on-pre-merge-SHA race by construction).
|
|
144
|
+
- T9534: `release-fanout.yml.tmpl` + 11 fanout placeholders + snapshot test
|
|
145
|
+
(five independent best-effort jobs gated on env toggles, every job
|
|
146
|
+
carries `continue-on-error: true` so fanout failures cannot mark the
|
|
147
|
+
release as failed; fanout jobs MUST NOT be required status checks per
|
|
148
|
+
R-244).
|
|
149
|
+
- T9535: `release-rollback.yml.tmpl` + rollback placeholders (`NPM_PACKAGES`,
|
|
150
|
+
`CARGO_CRATES`) + snapshot test (current task — `workflow_dispatch`-only
|
|
151
|
+
rollback with 4 jobs `validate` → `revert` → `deprecate` →
|
|
152
|
+
`reconcile-rollback`. The `revert` job opens a revert PR against `main`
|
|
153
|
+
via `gh pr create --label rollback` — NEVER pushes directly to `main`
|
|
154
|
+
per ADR-065. The `deprecate` job is best-effort
|
|
155
|
+
(`continue-on-error: true`); reconcile runs whenever validate succeeded
|
|
156
|
+
so the provenance graph records the operator's intent even if a
|
|
157
|
+
downstream side-effect failed).
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# CLEO release pipeline — Best-effort fanout workflow.
|
|
2
|
+
#
|
|
3
|
+
# Generated from packages/cleo/templates/workflows/release-fanout.yml.tmpl by
|
|
4
|
+
# `cleo init --workflows` (T9531). DO NOT EDIT the rendered file directly —
|
|
5
|
+
# extend via `.workflow-overrides.yml` per SPEC-T9345 R-260.
|
|
6
|
+
#
|
|
7
|
+
# Implements SPEC-T9345-release-pipeline-v2.md §5.3 (R-240 — R-244, R-260 —
|
|
8
|
+
# R-263). Triggers on `release: published` (the GitHub Release event, NOT
|
|
9
|
+
# `release: created` which fires on drafts). Each downstream job is an
|
|
10
|
+
# independent best-effort fanout — every job carries `continue-on-error:
|
|
11
|
+
# true` so a failed docs deploy, docker retag, sentinel notify, studio
|
|
12
|
+
# rebuild, or nightly trigger CANNOT mark the release itself as failed.
|
|
13
|
+
# These jobs MUST NOT be configured as required status checks (R-244).
|
|
14
|
+
#
|
|
15
|
+
# Placeholders (replaced at scaffold time — see workflows/README.md):
|
|
16
|
+
# <NODE_VERSION> Node.js version (e.g. "22.x")
|
|
17
|
+
# <INSTALL_CMD> Install command (e.g. "pnpm install --frozen-lockfile")
|
|
18
|
+
# <DOCS_BUILD_CMD> Docs build command (e.g. "pnpm --filter @cleocode/docs run build")
|
|
19
|
+
# <ENABLE_DOCS_DEPLOY> Toggle docs-deploy job ("true" | "false")
|
|
20
|
+
# <ENABLE_DOCKER_RETAG> Toggle docker-retag job ("true" | "false")
|
|
21
|
+
# <ENABLE_SENTINEL_NOTIFY> Toggle sentinel-notify job ("true" | "false")
|
|
22
|
+
# <ENABLE_STUDIO_DEPLOY> Toggle studio-deploy job ("true" | "false")
|
|
23
|
+
# <ENABLE_NIGHTLY_TRIGGER> Toggle nightly-trigger job ("true" | "false")
|
|
24
|
+
# <DOCKER_IMAGE> Docker image name (e.g. "cleocode/cleo")
|
|
25
|
+
# <DOCKER_HUB_USER> Docker Hub login user (e.g. "cleocode")
|
|
26
|
+
# <SENTINEL_WEBHOOK_URL> Sentinel webhook URL (HTTPS)
|
|
27
|
+
# <STUDIO_DEPLOY_HOOK> Studio deploy hook URL (HTTPS)
|
|
28
|
+
# (Angle-brackets in this doc comment are intentional — they avoid being
|
|
29
|
+
# substituted by the {{...}} regex pass. The placeholders below use {{...}}.)
|
|
30
|
+
|
|
31
|
+
name: Release Fanout
|
|
32
|
+
|
|
33
|
+
# R-240: trigger on `release: published` ONLY. Draft releases (which fire
|
|
34
|
+
# `release: created`) MUST NOT trigger the fanout — operators expect this
|
|
35
|
+
# to run AFTER the publish + tag workflow has shipped the artifacts.
|
|
36
|
+
on:
|
|
37
|
+
release:
|
|
38
|
+
types: [published]
|
|
39
|
+
|
|
40
|
+
# R-241: workflow-level grants the minimum read scope. Per-job permissions
|
|
41
|
+
# escalate ONLY for the jobs that need them (e.g. `pages: write` for docs
|
|
42
|
+
# deploy). No top-level write scope — fanout is intentionally read-only at
|
|
43
|
+
# the workflow level.
|
|
44
|
+
permissions:
|
|
45
|
+
contents: read
|
|
46
|
+
|
|
47
|
+
# R-243: serialize fanouts against the same release tag. cancel-in-progress
|
|
48
|
+
# is FALSE so an in-flight fanout completes rather than losing partial
|
|
49
|
+
# work (e.g. a half-pushed docker tag).
|
|
50
|
+
concurrency:
|
|
51
|
+
group: fanout-${{ github.event.release.tag_name }}
|
|
52
|
+
cancel-in-progress: false
|
|
53
|
+
|
|
54
|
+
# R-262: bash everywhere — no cross-platform shell drift across the fanout
|
|
55
|
+
# jobs (they all run on ubuntu-latest but the contract is explicit).
|
|
56
|
+
defaults:
|
|
57
|
+
run:
|
|
58
|
+
shell: bash
|
|
59
|
+
|
|
60
|
+
jobs:
|
|
61
|
+
# R-242 (1/5): deploy generated documentation site to GitHub Pages.
|
|
62
|
+
# continue-on-error: true so a docs-build regression cannot fail the
|
|
63
|
+
# release. Disabled by default — flip {{ENABLE_DOCS_DEPLOY}} to "true"
|
|
64
|
+
# at scaffold time. The flag is hoisted into env so the `if:` becomes a
|
|
65
|
+
# dynamic expression (avoids actionlint constant-expression warning).
|
|
66
|
+
docs-deploy:
|
|
67
|
+
name: Deploy docs to GitHub Pages
|
|
68
|
+
runs-on: ubuntu-latest
|
|
69
|
+
continue-on-error: true
|
|
70
|
+
timeout-minutes: 15
|
|
71
|
+
env:
|
|
72
|
+
ENABLE_DOCS_DEPLOY: '{{ENABLE_DOCS_DEPLOY}}'
|
|
73
|
+
if: ${{ env.ENABLE_DOCS_DEPLOY == 'true' }}
|
|
74
|
+
# R-241 (per-job): pages: write + id-token: write granted ONLY for the
|
|
75
|
+
# docs-deploy job — other fanout jobs MUST NOT inherit GitHub Pages
|
|
76
|
+
# write scope.
|
|
77
|
+
permissions:
|
|
78
|
+
contents: read
|
|
79
|
+
pages: write
|
|
80
|
+
id-token: write
|
|
81
|
+
steps:
|
|
82
|
+
# R-263: third-party Actions pinned to major+minor.
|
|
83
|
+
- name: Checkout
|
|
84
|
+
uses: actions/checkout@v4.1
|
|
85
|
+
with:
|
|
86
|
+
fetch-depth: 1
|
|
87
|
+
timeout-minutes: 5
|
|
88
|
+
|
|
89
|
+
- name: Set up Node.js
|
|
90
|
+
uses: actions/setup-node@v4.0
|
|
91
|
+
with:
|
|
92
|
+
node-version: '{{NODE_VERSION}}'
|
|
93
|
+
timeout-minutes: 3
|
|
94
|
+
|
|
95
|
+
- name: Install dependencies
|
|
96
|
+
run: {{INSTALL_CMD}}
|
|
97
|
+
timeout-minutes: 5
|
|
98
|
+
|
|
99
|
+
- name: Build docs
|
|
100
|
+
run: {{DOCS_BUILD_CMD}}
|
|
101
|
+
timeout-minutes: 10
|
|
102
|
+
|
|
103
|
+
- name: Configure Pages
|
|
104
|
+
uses: actions/configure-pages@v5.0
|
|
105
|
+
timeout-minutes: 2
|
|
106
|
+
|
|
107
|
+
- name: Upload Pages artifact
|
|
108
|
+
uses: actions/upload-pages-artifact@v3.0
|
|
109
|
+
with:
|
|
110
|
+
path: docs/dist
|
|
111
|
+
timeout-minutes: 5
|
|
112
|
+
|
|
113
|
+
- name: Deploy to GitHub Pages
|
|
114
|
+
uses: actions/deploy-pages@v4.0
|
|
115
|
+
timeout-minutes: 5
|
|
116
|
+
|
|
117
|
+
# R-242 (2/5): retag the published docker image to `latest`. Failure here
|
|
118
|
+
# does NOT roll back the release — operators can re-run manually.
|
|
119
|
+
docker-retag:
|
|
120
|
+
name: Retag docker image to latest
|
|
121
|
+
runs-on: ubuntu-latest
|
|
122
|
+
continue-on-error: true
|
|
123
|
+
timeout-minutes: 10
|
|
124
|
+
env:
|
|
125
|
+
ENABLE_DOCKER_RETAG: '{{ENABLE_DOCKER_RETAG}}'
|
|
126
|
+
DOCKER_IMAGE: '{{DOCKER_IMAGE}}'
|
|
127
|
+
DOCKER_HUB_USER: '{{DOCKER_HUB_USER}}'
|
|
128
|
+
VERSION: ${{ github.event.release.tag_name }}
|
|
129
|
+
if: ${{ env.ENABLE_DOCKER_RETAG == 'true' }}
|
|
130
|
+
steps:
|
|
131
|
+
- name: Log in to Docker Hub
|
|
132
|
+
run: |
|
|
133
|
+
set -euo pipefail
|
|
134
|
+
echo "${{ secrets.DOCKER_HUB_TOKEN }}" | \
|
|
135
|
+
docker login -u "$DOCKER_HUB_USER" --password-stdin
|
|
136
|
+
timeout-minutes: 3
|
|
137
|
+
|
|
138
|
+
- name: Pull, retag, push
|
|
139
|
+
run: |
|
|
140
|
+
set -euo pipefail
|
|
141
|
+
docker pull "${DOCKER_IMAGE}:${VERSION}"
|
|
142
|
+
docker tag "${DOCKER_IMAGE}:${VERSION}" "${DOCKER_IMAGE}:latest"
|
|
143
|
+
docker push "${DOCKER_IMAGE}:latest"
|
|
144
|
+
timeout-minutes: 5
|
|
145
|
+
|
|
146
|
+
# R-242 (3/5): POST a `release.published` event to the Sentinel webhook
|
|
147
|
+
# so downstream monitoring can pick the release up. Best-effort — a
|
|
148
|
+
# webhook outage MUST NOT mark the release as failed.
|
|
149
|
+
sentinel-notify:
|
|
150
|
+
name: Notify Sentinel of release
|
|
151
|
+
runs-on: ubuntu-latest
|
|
152
|
+
continue-on-error: true
|
|
153
|
+
timeout-minutes: 5
|
|
154
|
+
env:
|
|
155
|
+
ENABLE_SENTINEL_NOTIFY: '{{ENABLE_SENTINEL_NOTIFY}}'
|
|
156
|
+
SENTINEL_WEBHOOK_URL: '{{SENTINEL_WEBHOOK_URL}}'
|
|
157
|
+
SENTINEL_TOKEN: ${{ secrets.SENTINEL_TOKEN }}
|
|
158
|
+
VERSION: ${{ github.event.release.tag_name }}
|
|
159
|
+
RELEASE_URL: ${{ github.event.release.html_url }}
|
|
160
|
+
if: ${{ env.ENABLE_SENTINEL_NOTIFY == 'true' }}
|
|
161
|
+
steps:
|
|
162
|
+
- name: POST release.published to Sentinel
|
|
163
|
+
run: |
|
|
164
|
+
set -euo pipefail
|
|
165
|
+
curl -fSL -X POST "$SENTINEL_WEBHOOK_URL" \
|
|
166
|
+
-H 'Content-Type: application/json' \
|
|
167
|
+
-H "Authorization: Bearer ${SENTINEL_TOKEN}" \
|
|
168
|
+
-d "{\"event\":\"release.published\",\"version\":\"${VERSION}\",\"url\":\"${RELEASE_URL}\"}"
|
|
169
|
+
timeout-minutes: 3
|
|
170
|
+
|
|
171
|
+
# R-242 (4/5): trigger a Studio rebuild via deploy hook. Studio runs
|
|
172
|
+
# outside this repo, so this job is a fire-and-forget POST.
|
|
173
|
+
studio-deploy:
|
|
174
|
+
name: Trigger Studio rebuild
|
|
175
|
+
runs-on: ubuntu-latest
|
|
176
|
+
continue-on-error: true
|
|
177
|
+
timeout-minutes: 20
|
|
178
|
+
env:
|
|
179
|
+
ENABLE_STUDIO_DEPLOY: '{{ENABLE_STUDIO_DEPLOY}}'
|
|
180
|
+
STUDIO_DEPLOY_HOOK: '{{STUDIO_DEPLOY_HOOK}}'
|
|
181
|
+
STUDIO_DEPLOY_TOKEN: ${{ secrets.STUDIO_DEPLOY_TOKEN }}
|
|
182
|
+
VERSION: ${{ github.event.release.tag_name }}
|
|
183
|
+
if: ${{ env.ENABLE_STUDIO_DEPLOY == 'true' }}
|
|
184
|
+
steps:
|
|
185
|
+
- name: POST to Studio deploy hook
|
|
186
|
+
run: |
|
|
187
|
+
set -euo pipefail
|
|
188
|
+
curl -fSL -X POST "$STUDIO_DEPLOY_HOOK" \
|
|
189
|
+
-H "Authorization: Bearer ${STUDIO_DEPLOY_TOKEN}" \
|
|
190
|
+
-H 'Content-Type: application/json' \
|
|
191
|
+
-d "{\"version\":\"${VERSION}\"}"
|
|
192
|
+
timeout-minutes: 10
|
|
193
|
+
|
|
194
|
+
# R-242 (5/5): dispatch the nightly e2e workflow against the freshly
|
|
195
|
+
# published release version. Decoupled from the release path — a failed
|
|
196
|
+
# dispatch is logged but does NOT fail the release.
|
|
197
|
+
nightly-trigger:
|
|
198
|
+
name: Dispatch nightly e2e for release
|
|
199
|
+
runs-on: ubuntu-latest
|
|
200
|
+
continue-on-error: true
|
|
201
|
+
timeout-minutes: 3
|
|
202
|
+
env:
|
|
203
|
+
ENABLE_NIGHTLY_TRIGGER: '{{ENABLE_NIGHTLY_TRIGGER}}'
|
|
204
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
205
|
+
VERSION: ${{ github.event.release.tag_name }}
|
|
206
|
+
if: ${{ env.ENABLE_NIGHTLY_TRIGGER == 'true' }}
|
|
207
|
+
steps:
|
|
208
|
+
- name: Dispatch nightly e2e
|
|
209
|
+
run: |
|
|
210
|
+
set -euo pipefail
|
|
211
|
+
gh workflow run nightly-e2e.yml \
|
|
212
|
+
--repo "${{ github.repository }}" \
|
|
213
|
+
-f release_version="$VERSION"
|
|
214
|
+
timeout-minutes: 2
|