@rizom/ops 0.2.0-alpha.285 → 0.2.0-alpha.287

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rizom/ops",
3
- "version": "0.2.0-alpha.285",
3
+ "version": "0.2.0-alpha.287",
4
4
  "description": "Operator CLI for managing private brain fleet registry repos",
5
5
  "keywords": [
6
6
  "brains",
@@ -12,8 +12,7 @@ on:
12
12
  - cron: "17 6 * * 1-5"
13
13
 
14
14
  permissions:
15
- contents: write
16
- pull-requests: write
15
+ contents: read
17
16
 
18
17
  concurrency:
19
18
  group: upgrade
@@ -23,7 +22,21 @@ jobs:
23
22
  upgrade:
24
23
  runs-on: ubuntu-latest
25
24
  steps:
25
+ - name: Require upgrade App configuration
26
+ env:
27
+ APP_ID: ${{ vars.OPS_UPGRADE_APP_ID }}
28
+ run: |
29
+ if [ -z "$APP_ID" ]; then
30
+ echo "OPS_UPGRADE_APP_ID is not set." >&2
31
+ echo "Configure the upgrade GitHub App as described in docs/operator-playbook.md." >&2
32
+ exit 1
33
+ fi
34
+
35
+ # No credential is persisted in .git/config while the workflow installs
36
+ # and executes a freshly published @rizom/ops package.
26
37
  - uses: actions/checkout@v5
38
+ with:
39
+ persist-credentials: false
27
40
 
28
41
  - uses: oven-sh/setup-bun@v2
29
42
 
@@ -35,14 +48,32 @@ jobs:
35
48
  VERSION_INPUT: ${{ inputs.version }}
36
49
  run: bunx brains-ops upgrade . --to "${VERSION_INPUT:-latest}"
37
50
 
38
- - name: Open upgrade PR
39
- env:
40
- GH_TOKEN: ${{ github.token }}
51
+ - name: Detect upgrade changes
52
+ id: upgrade-changes
41
53
  run: |
42
54
  if [ -z "$(git status --porcelain)" ]; then
43
55
  echo "Already up to date."
44
- exit 0
56
+ echo "changed=false" >> "$GITHUB_OUTPUT"
57
+ else
58
+ echo "changed=true" >> "$GITHUB_OUTPUT"
45
59
  fi
60
+
61
+ - name: Create repository-scoped upgrade token
62
+ if: steps.upgrade-changes.outputs.changed == 'true'
63
+ id: upgrade-token
64
+ uses: actions/create-github-app-token@v2
65
+ with:
66
+ app-id: ${{ vars.OPS_UPGRADE_APP_ID }}
67
+ private-key: ${{ secrets.OPS_UPGRADE_APP_PRIVATE_KEY }}
68
+ permission-contents: write
69
+ permission-pull-requests: write
70
+ permission-workflows: write
71
+
72
+ - name: Open upgrade PR
73
+ if: steps.upgrade-changes.outputs.changed == 'true'
74
+ env:
75
+ GH_TOKEN: ${{ steps.upgrade-token.outputs.token }}
76
+ run: |
46
77
  VERSION=$(bun -e 'console.log(JSON.parse(await Bun.file("package.json").text()).devDependencies["@rizom/ops"])')
47
78
  BRANCH="ops/upgrade-rizom-ops-$VERSION"
48
79
  git config user.name "github-actions[bot]"
@@ -50,9 +81,14 @@ jobs:
50
81
  git checkout -B "$BRANCH"
51
82
  git add -A
52
83
  git commit -m "chore(ops): upgrade @rizom/ops to $VERSION"
53
- git push --force -u origin "$BRANCH"
84
+ git push --force \
85
+ "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" \
86
+ "$BRANCH"
87
+ if [ -n "$(gh pr list --head "$BRANCH" --state open --json number --jq '.[].number')" ]; then
88
+ echo "PR already open for $BRANCH"
89
+ exit 0
90
+ fi
54
91
  gh pr create \
55
92
  --title "chore(ops): upgrade @rizom/ops to $VERSION" \
56
93
  --body "Automated operator tooling upgrade. Review the scaffold diff, then merge; deploys stay operator-dispatched." \
57
- --head "$BRANCH" \
58
- || echo "PR already open for $BRANCH"
94
+ --head "$BRANCH"
@@ -51,4 +51,6 @@ When a push changes only deploy contract files, CI prints `No affected user conf
51
51
 
52
52
  `render` owns the observational `views/users.md` projection. Reconcile owns generated per-user config and never rewrites observed status rows.
53
53
 
54
+ The Upgrade workflow uses a repository-scoped GitHub App token because an Actions `GITHUB_TOKEN` cannot update generated files under `.github/workflows/`. Checkout persists no credential, and the App token is minted only after the freshly published tooling finishes and only when there is a change to push. Configure the App and its `OPS_UPGRADE_APP_ID` Actions variable and `OPS_UPGRADE_APP_PRIVATE_KEY` Actions secret as described in `docs/operator-playbook.md`. If token creation or the upgrade push fails, stop; do not substitute an operator's personal credentials.
55
+
54
56
  Use `docs/canonical-crossover-record.md` to record exact forward and rollback artifact pins before an approved crossover window.
@@ -120,12 +120,25 @@ Preview hosts use the shape `<handle>-preview.rizom.ai`, so one wildcard origin
120
120
 
121
121
  ## Upgrading operator behavior
122
122
 
123
- When `@rizom/ops` changes the scaffolded deploy contract:
123
+ The pilot repository pins `@rizom/ops` in `package.json`. The scheduled and manually dispatched Upgrade workflow owns routine upgrades to that pin. It refreshes the scaffold on a branch and opens a reviewable PR; it does not change runtime desired state or authorize a deployment.
124
124
 
125
- 1. bump `@rizom/ops` in `package.json`
126
- 2. rerun the relevant scaffold/reconcile flow
127
- 3. review the resulting changes to `.env.schema`, `deploy/scripts/`, and workflows in git
128
- 4. commit the updated deploy artifacts together
125
+ Because scaffold refreshes can update `.github/workflows/*`, the workflow must not push with its Actions `GITHUB_TOKEN`. Configure a dedicated GitHub App:
126
+
127
+ 1. Install it only on this pilot repository.
128
+ 2. Grant repository permissions `Contents: Read and write`, `Pull requests: Read and write`, and `Workflows: Read and write`; grant nothing else.
129
+ 3. Store its App ID as the repository Actions variable `OPS_UPGRADE_APP_ID`.
130
+ 4. Store its private key as the repository Actions secret `OPS_UPGRADE_APP_PRIVATE_KEY`.
131
+
132
+ The workflow explicitly requests only those three permissions. Checkout persists no credential. After the freshly published `@rizom/ops` finishes, the workflow checks whether it produced a change; only then does it mint a short-lived, repository-scoped App token for the push-and-open-PR steps. A credential that can rewrite `.github/workflows/` therefore does not exist while upgraded package code runs.
133
+
134
+ If `OPS_UPGRADE_APP_ID` is unset, or token creation, branch push, or PR creation fails, the run stops with a non-zero status. Repair the CI credential path; never fall back to an operator's personal SSH key or token.
135
+
136
+ Adopting this credential flow in an existing pilot repository requires one explicitly reviewed bootstrap PR because the old Upgrade workflow cannot update itself. After that merge, routine upgrades run entirely in CI:
137
+
138
+ 1. dispatch Upgrade with an exact version, or let its schedule select `latest`;
139
+ 2. review the generated package, lockfile, deploy-script, and workflow diff;
140
+ 3. merge the upgrade PR only after its checks pass;
141
+ 4. change runtime desired state separately through the approved canary or fleet rollout flow.
129
142
 
130
143
  ## Canonical verification notes
131
144