Skip to content

Commit 7288922

Browse files
committed
chore(automation): simplify repository delivery boundaries
- align contract admission and Dependabot with intentional adoption - remove redundant CI and Pages authorities - move native extension publishing into a repository script
1 parent c4ec933 commit 7288922

9 files changed

Lines changed: 109 additions & 275 deletions

File tree

‎.github/dependabot.yml‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ updates:
2121
semver-major-days: 30
2222
semver-minor-days: 7
2323
semver-patch-days: 3
24+
ignore:
25+
- dependency-name: '*'
26+
update-types:
27+
- version-update:semver-major
2428
groups:
2529
production-dependencies:
2630
dependency-type: production

‎.github/workflows/ci.yml‎

Lines changed: 0 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ on:
1212
- synchronize
1313
- reopened
1414
- ready_for_review
15-
merge_group:
16-
types:
17-
- checks_requested
1815
workflow_dispatch:
1916

2017
permissions:
@@ -25,7 +22,6 @@ concurrency:
2522
group: >-
2623
client-checks-${{
2724
github.event.pull_request.number ||
28-
github.event.merge_group.head_sha ||
2925
github.ref
3026
}}
3127
cancel-in-progress: true
@@ -91,60 +87,6 @@ jobs:
9187
echo "- Runtime contract: \`$CONTRACT_REVISION\`"
9288
} >> "$GITHUB_STEP_SUMMARY"
9389
94-
database-contract:
95-
name: Database contract
96-
needs: core-release
97-
runs-on: ubuntu-latest
98-
steps:
99-
- name: Checkout
100-
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
101-
with:
102-
fetch-depth: 0
103-
104-
- name: Install the pinned pnpm release
105-
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
106-
with:
107-
version: 11.11.0
108-
109-
- name: Set up Node
110-
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
111-
with:
112-
node-version-file: package.json
113-
cache: pnpm
114-
registry-url: https://npm.pkg.github.com
115-
scope: '@inkcre'
116-
117-
- name: Install the frozen workspace
118-
run: pnpm install --frozen-lockfile
119-
env:
120-
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
121-
122-
- name: Authenticate to GHCR
123-
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
124-
with:
125-
registry: ghcr.io
126-
username: ${{ github.actor }}
127-
password: ${{ secrets.GITHUB_TOKEN }}
128-
129-
- name: Generate types from the selected raw schema
130-
run: pnpm contract:sync -- --image "${{ needs.core-release.outputs.image }}"
131-
132-
- name: Upload the generated database contract
133-
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
134-
with:
135-
name: generated-database-contract-${{ github.sha }}
136-
path: |
137-
packages/core/src/database/database.generated.ts
138-
packages/core/src/database/runtime-contract.generated.json
139-
if-no-files-found: error
140-
retention-days: 7
141-
142-
- name: Reject a stale checked-in database contract
143-
run: >-
144-
git diff --exit-code --
145-
packages/core/src/database/database.generated.ts
146-
packages/core/src/database/runtime-contract.generated.json
147-
14890
workspace:
14991
name: Workspace contract
15092
runs-on: ubuntu-latest
@@ -182,39 +124,6 @@ jobs:
182124
--core-package packages/core/package.json
183125
--artifact-directory extensions/twitter/dist/client-web
184126
185-
toolchain-shadow:
186-
name: Type-aware and TypeScript 7 shadow
187-
runs-on: ubuntu-latest
188-
steps:
189-
- name: Checkout
190-
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
191-
192-
- name: Install the pinned pnpm release
193-
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
194-
with:
195-
version: 11.11.0
196-
197-
- name: Set up Node
198-
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
199-
with:
200-
node-version-file: package.json
201-
cache: pnpm
202-
registry-url: https://npm.pkg.github.com
203-
scope: '@inkcre'
204-
205-
- name: Install the frozen workspace
206-
run: pnpm install --frozen-lockfile
207-
env:
208-
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
209-
210-
- name: Run type-aware Oxlint
211-
continue-on-error: true
212-
run: pnpm lint:type-aware
213-
214-
- name: Run the native TypeScript 7 preview
215-
continue-on-error: true
216-
run: pnpm type-check:ts7
217-
218127
peer-database:
219128
name: client-web E2E
220129
needs: core-release

‎.github/workflows/extension-release.yml‎

Lines changed: 1 addition & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -107,79 +107,4 @@ jobs:
107107
INKCRE_EXTENSION_REGISTRY_TOKEN: ${{ secrets.INKCRE_EXTENSION_REGISTRY_TOKEN }}
108108
SOURCE_REPOSITORY: https://github.com/${{ github.repository }}
109109
SOURCE_REVISION: ${{ github.sha }}
110-
run: |
111-
test -n "$INKCRE_EXTENSION_REGISTRY_TOKEN"
112-
mkdir -p .extension-delivery
113-
114-
for package_path in extensions/*/package.json; do
115-
descriptor="$(node --input-type=module --eval '
116-
import { readFile } from "node:fs/promises"
117-
import path from "node:path"
118-
const packagePath = process.argv[1]
119-
const manifest = JSON.parse(await readFile(packagePath, "utf8"))
120-
if (!manifest.inkcre?.module_federation) process.exit(0)
121-
process.stdout.write([path.basename(path.dirname(packagePath)), manifest.inkcre.name, manifest.version].join("\t"))
122-
' "$package_path")"
123-
if [[ -z "$descriptor" ]]; then
124-
continue
125-
fi
126-
IFS=$'\t' read -r extension_directory extension_path release_path <<< "$descriptor"
127-
128-
delivery_directory=".extension-delivery/$extension_directory"
129-
artifact_directory="extensions/$extension_directory/dist/client-web"
130-
mkdir -p "$delivery_directory"
131-
public_descriptor="$delivery_directory/public-release.json"
132-
status="$(curl --silent --show-error --output "$public_descriptor" --write-out '%{http_code}' \
133-
"${INKCRE_EXTENSION_REGISTRY_URL%/}/v1/extensions/${extension_path}/releases/${release_path}")"
134-
if [[ "$status" == '200' ]]; then
135-
has_native_association="$(node --input-type=module --eval 'import { readFile } from "node:fs/promises"; const release = JSON.parse(await readFile(process.argv[1], "utf8")); process.stdout.write(String(release.module_federation !== null))' "$public_descriptor")"
136-
elif [[ "$status" == '404' ]]; then
137-
has_native_association=false
138-
else
139-
echo "Cannot determine $extension_path $release_path Registry state: HTTP $status." >&2
140-
exit 1
141-
fi
142-
if [[ "$has_native_association" == 'true' ]]; then
143-
echo "$extension_path $release_path is already published." >> "$GITHUB_STEP_SUMMARY"
144-
continue
145-
fi
146-
147-
node scripts/verify-native-extension-distribution.mjs prepare-body \
148-
--package "$package_path" \
149-
--core-package packages/core/package.json \
150-
--artifact-directory "$artifact_directory" \
151-
--source-repository "$SOURCE_REPOSITORY" \
152-
--source-revision "$SOURCE_REVISION" \
153-
--build-id "client-web-extension-release-${GITHUB_RUN_ID}" \
154-
--output "$delivery_directory/prepare.json"
155-
(
156-
cd "$artifact_directory"
157-
zip -q -r "$GITHUB_WORKSPACE/$delivery_directory/snapshot.zip" .
158-
)
159-
160-
curl --fail-with-body --silent --show-error \
161-
--request POST \
162-
--header "Authorization: Bearer $INKCRE_EXTENSION_REGISTRY_TOKEN" \
163-
--header 'Content-Type: application/json' \
164-
--data-binary "@$delivery_directory/prepare.json" \
165-
"${INKCRE_EXTENSION_REGISTRY_URL%/}/v1/extensions/${extension_path}/releases" \
166-
> "$delivery_directory/prepared-release.json"
167-
curl --fail-with-body --silent --show-error \
168-
--request POST \
169-
--header "Authorization: Bearer $INKCRE_EXTENSION_REGISTRY_TOKEN" \
170-
--form "content=@$delivery_directory/snapshot.zip;type=application/zip" \
171-
"${INKCRE_EXTENSION_REGISTRY_URL%/}/v1/extensions/${extension_path}/releases/${release_path}/module-federation" \
172-
> "$delivery_directory/uploaded-release.json"
173-
curl --fail-with-body --silent --show-error \
174-
--request POST \
175-
--header "Authorization: Bearer $INKCRE_EXTENSION_REGISTRY_TOKEN" \
176-
"${INKCRE_EXTENSION_REGISTRY_URL%/}/v1/extensions/${extension_path}/releases/${release_path}/publish" \
177-
> "$delivery_directory/published-release.json"
178-
node scripts/verify-native-extension-distribution.mjs verify-public \
179-
--registry-url "$INKCRE_EXTENSION_REGISTRY_URL" \
180-
--package "$package_path" \
181-
--core-package packages/core/package.json \
182-
--artifact-directory "$artifact_directory" \
183-
--output "$delivery_directory/verification.json"
184-
echo "$extension_path $release_path published and verified." >> "$GITHUB_STEP_SUMMARY"
185-
done
110+
run: bash scripts/publish-native-extensions.sh

‎.github/workflows/pages-deploy.yml‎

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -89,21 +89,6 @@ jobs:
8989
working-directory: release
9090
run: pnpm build
9191

92-
- name: Reverify main before Pages delivery
93-
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
94-
env:
95-
SOURCE_SHA: ${{ needs.identity.outputs.source_sha }}
96-
with:
97-
script: |
98-
const currentMain = await github.rest.git.getRef({
99-
owner: context.repo.owner,
100-
repo: context.repo.repo,
101-
ref: 'heads/main',
102-
})
103-
if (currentMain.data.object.sha !== process.env.SOURCE_SHA) {
104-
core.setFailed('Main changed after the release build; refusing Pages delivery.')
105-
}
106-
10792
- name: Deploy to Cloudflare Pages
10893
id: pages
10994
uses: cloudflare/wrangler-action@ebbaa1584979971c8614a24965b4405ff95890e0 # v4.0.0

‎.github/workflows/pages-preview.yml‎

Lines changed: 0 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ on:
1212
permissions:
1313
contents: read
1414
packages: read
15-
pull-requests: read
1615

1716
jobs:
1817
identity:
@@ -57,7 +56,6 @@ jobs:
5756
contents: read
5857
deployments: write
5958
packages: read
60-
pull-requests: read
6159
runs-on: ubuntu-latest
6260
timeout-minutes: 25
6361
environment: preview
@@ -123,61 +121,6 @@ jobs:
123121
cp -R .preview-registry/. apps/client-web/dist/
124122
cp -R apps/client-web/dist "$GITHUB_WORKSPACE/.pages-preview"
125123
126-
- name: Reverify pull-request identity before delivery
127-
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
128-
env:
129-
PREVIEW_BRANCH: ${{ needs.identity.outputs.branch }}
130-
PREVIEW_HEAD_SHA: ${{ needs.identity.outputs.head_sha }}
131-
PULL_NUMBER: ${{ needs.identity.outputs.pull_number }}
132-
with:
133-
script: |
134-
const expectedBranch = `preview/client-web/pr-${process.env.PULL_NUMBER}`
135-
if (process.env.PREVIEW_BRANCH !== expectedBranch) {
136-
core.setFailed(`Unexpected Pages preview branch: ${process.env.PREVIEW_BRANCH}`)
137-
return
138-
}
139-
const { data: pull } = await github.rest.pulls.get({
140-
owner: context.repo.owner,
141-
repo: context.repo.repo,
142-
pull_number: Number(process.env.PULL_NUMBER),
143-
})
144-
if (
145-
pull.state !== 'open' ||
146-
pull.base.ref !== 'main' ||
147-
pull.head.sha !== process.env.PREVIEW_HEAD_SHA ||
148-
pull.head.repo?.full_name !== `${context.repo.owner}/${context.repo.repo}`
149-
) {
150-
core.setFailed('Pull-request identity changed after the exact-head build.')
151-
}
152-
153-
- name: Register the pull-request deployment
154-
id: github-deployment
155-
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
156-
env:
157-
PREVIEW_HEAD_SHA: ${{ needs.identity.outputs.head_sha }}
158-
PULL_NUMBER: ${{ needs.identity.outputs.pull_number }}
159-
with:
160-
script: |
161-
const { data: deployment } = await github.rest.repos.createDeployment({
162-
owner: context.repo.owner,
163-
repo: context.repo.repo,
164-
ref: process.env.PREVIEW_HEAD_SHA,
165-
environment: 'preview',
166-
description: `Cloudflare Pages preview for PR #${process.env.PULL_NUMBER}`,
167-
auto_merge: false,
168-
required_contexts: [],
169-
transient_environment: true,
170-
production_environment: false,
171-
})
172-
core.setOutput('deployment_id', String(deployment.id))
173-
await github.rest.repos.createDeploymentStatus({
174-
owner: context.repo.owner,
175-
repo: context.repo.repo,
176-
deployment_id: deployment.id,
177-
state: 'in_progress',
178-
log_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
179-
})
180-
181124
- name: Deploy to the isolated Pages preview branch
182125
id: pages
183126
uses: cloudflare/wrangler-action@ebbaa1584979971c8614a24965b4405ff95890e0 # v4.0.0
@@ -193,25 +136,3 @@ jobs:
193136
--branch=${{ needs.identity.outputs.branch }}
194137
--commit-hash=${{ needs.identity.outputs.head_sha }}
195138
--commit-dirty=false
196-
197-
- name: Report the pull-request deployment
198-
if: ${{ always() && steps.github-deployment.outputs.deployment_id != '' }}
199-
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
200-
env:
201-
DEPLOYMENT_ID: ${{ steps.github-deployment.outputs.deployment_id }}
202-
JOB_STATUS: ${{ job.status }}
203-
PREVIEW_URL: ${{ steps.pages.outputs.pages-deployment-alias-url }}
204-
with:
205-
script: |
206-
const success = process.env.JOB_STATUS === 'success'
207-
await github.rest.repos.createDeploymentStatus({
208-
owner: context.repo.owner,
209-
repo: context.repo.repo,
210-
deployment_id: Number(process.env.DEPLOYMENT_ID),
211-
state: success ? 'success' : 'failure',
212-
description: success ? 'Pull-request preview is ready' : 'Pull-request preview failed',
213-
log_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
214-
...(success && process.env.PREVIEW_URL
215-
? { environment_url: process.env.PREVIEW_URL }
216-
: {}),
217-
})

‎AGENTS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Reason in English. Communicate with humans in Chinese.
3333
- Diagnose: `pnpm run doctor` (`pnpm doctor` is a different pnpm command).
3434
- Develop: `pnpm dev`, `pnpm dev:all`, or an explicit source lane documented in `docs/40-deployment/development-runtime.md`.
3535
- Required verification: `pnpm check`; required production outputs: `pnpm build`.
36-
- Shadow verification: `pnpm lint:type-aware` and `pnpm type-check:ts7`.
36+
- Optional local migration probes: `pnpm lint:type-aware` and `pnpm type-check:ts7`.
3737
- Follow the organization-wide [Verification and Test Policy](https://github.com/InKCre/.github/blob/main/TESTING.md).
3838
The admitted Playwright E2E suites do not authorize new automation by analogy.
3939
- Follow `.agents/prompts/code-for-human.md` for source changes.

‎docs/40-deployment/development-runtime.md‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,13 @@ accepts only a ready development runtime, and resets only this worktree's client
8888
resources. Client-web refuses to reset or stop an external core-py runtime; recovery and cleanup
8989
must go through core-py. Browser E2E always creates and removes its own isolated database runtime.
9090

91-
The database contract is generated from the selected immutable core release. CI regenerates and
92-
checks it, runs the real core service in an isolated browser/database chain, and rejects a moved
93-
`stable` selection before admission. Pull-request evidence does not establish source-branch or
94-
migration equality between repositories.
91+
The checked database projection records the contract revision intentionally adopted by this
92+
consumer. Update it with `pnpm contract:sync` when client work adopts a newer compatible revision;
93+
an unrelated pull request does not chase a moving `stable` channel. CI still resolves `stable` once
94+
to an immutable image and runs that real core service through the isolated browser/database chain,
95+
which proves the checked client remains compatible with current delivery. A breaking contract
96+
revision requires the coordinated producer-first migration defined by the shared contract.
97+
Pull-request evidence does not establish source-branch or migration equality between repositories.
9598

9699
## Operator Commands
97100

‎scripts/check-local-runtime-contract.mjs‎

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,21 @@ if (
5050
if (await exists('.node-version')) {
5151
errors.push('.node-version must remain absent; pnpm devEngines.runtime owns Node')
5252
}
53-
for (const [path, expectedNodeFiles] of [
54-
['.github/workflows/ci.yml', Array(6).fill('package.json')],
55-
['.github/workflows/pages-cleanup.yml', ['controller/package.json']],
56-
['.github/workflows/pages-preview.yml', ['candidate/package.json']],
57-
['.github/workflows/pages-deploy.yml', ['release/package.json']],
53+
for (const [path, expectedNodeFile] of [
54+
['.github/workflows/ci.yml', 'package.json'],
55+
['.github/workflows/pages-cleanup.yml', 'controller/package.json'],
56+
['.github/workflows/pages-preview.yml', 'candidate/package.json'],
57+
['.github/workflows/pages-deploy.yml', 'release/package.json'],
5858
]) {
5959
const workflow = await readFile(`${repoRoot}/${path}`, 'utf8')
6060
const configuredNodeFiles = [...workflow.matchAll(/node-version-file:\s*(\S+)/g)].map(
6161
(match) => match[1]
6262
)
63-
if (JSON.stringify(configuredNodeFiles) !== JSON.stringify(expectedNodeFiles)) {
64-
errors.push(
65-
`${path} must derive Node setups from ${expectedNodeFiles.join(', ')} in that order`
66-
)
63+
if (
64+
configuredNodeFiles.length === 0 ||
65+
configuredNodeFiles.some((nodeFile) => nodeFile !== expectedNodeFile)
66+
) {
67+
errors.push(`${path} must derive every Node setup from ${expectedNodeFile}`)
6768
}
6869
}
6970
if (rootPackage.devDependencies?.portless !== '0.12.0') {

0 commit comments

Comments
 (0)