ci(web): surface pending manual deploys
Annotate green main builds with the exact manual deployment command while preserving the credential-free, approval-gated Cloudflare boundary.
This commit is contained in:
@@ -52,6 +52,25 @@ jobs:
|
||||
- name: Build production site
|
||||
run: npm run build
|
||||
|
||||
deploy-reminder:
|
||||
name: Deployment approval needed
|
||||
runs-on: ubuntu-latest
|
||||
needs: lint
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
steps:
|
||||
- name: Surface the manual deployment gate
|
||||
env:
|
||||
REVISION: ${{ github.sha }}
|
||||
run: |
|
||||
echo "::notice title=Web deployment approval needed::Revision ${REVISION} passed the web gates but is not deployed. Dispatch web.yml on main to publish it."
|
||||
{
|
||||
echo "## Web deployment approval needed"
|
||||
echo
|
||||
echo "Revision \`${REVISION}\` passed the web gates but has **not** been deployed."
|
||||
echo
|
||||
echo "A maintainer can publish it with \`gh workflow run web.yml --repo Hmbown/CodeWhale --ref main\`."
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
deploy:
|
||||
name: Deploy to Cloudflare
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -18,6 +18,9 @@ runs against Pi 0.8.41 and by dogfooding repeated manual compaction.
|
||||
|
||||
- `web_search` defaults to Firecrawl Cloud without an API key; keyless requests
|
||||
are headerless and quota-bounded, while an optional user key raises limits.
|
||||
- Green web builds on `main` now emit an actionable manual-deploy reminder, so
|
||||
site changes cannot quietly appear shipped while Cloudflare still serves an
|
||||
older revision.
|
||||
- Mistral AI is a first-class provider route, including Codestral models,
|
||||
first-party reasoning support, authentication, picker entries, and aliases.
|
||||
- Headless `Bash` can transfer explicitly requested persistent Unix services
|
||||
|
||||
@@ -42,6 +42,10 @@ git rev-parse origin/main
|
||||
gh workflow run web.yml --repo Hmbown/CodeWhale --ref main
|
||||
```
|
||||
|
||||
Every green push to `main` also emits a `Deployment approval needed` workflow
|
||||
notice with that command. The reminder does not receive Cloudflare credentials
|
||||
and cannot deploy; it keeps the manual production approval boundary visible.
|
||||
|
||||
The manual job records the pre-deploy source drift, builds the OpenNext bundle,
|
||||
deploys only after the protected Cloudflare inputs pass, and then requires the
|
||||
public `/api/facts` receipt to report the exact workflow SHA. A credential-free
|
||||
|
||||
@@ -127,6 +127,7 @@ function jobBlock(source: string, job: string) {
|
||||
describe("web workflow deploy trigger contract", () => {
|
||||
const workflow = readWebWorkflow();
|
||||
const deploy = jobBlock(workflow, "deploy");
|
||||
const deployReminder = jobBlock(workflow, "deploy-reminder");
|
||||
|
||||
it("still runs lint on pushes and pull requests", () => {
|
||||
expect(workflow).toContain(" push:\n branches: [master, main]");
|
||||
@@ -151,6 +152,16 @@ describe("web workflow deploy trigger contract", () => {
|
||||
expect(deploy).toContain("needs: lint");
|
||||
});
|
||||
|
||||
it("surfaces an actionable deployment reminder after a green main push", () => {
|
||||
expect(deployReminder).toContain("needs: lint");
|
||||
expect(deployReminder).toContain(
|
||||
"github.event_name == 'push' && github.ref == 'refs/heads/main'",
|
||||
);
|
||||
expect(deployReminder).toContain("::notice title=Web deployment approval needed::");
|
||||
expect(deployReminder).toContain("gh workflow run web.yml");
|
||||
expect(deployReminder).not.toContain("npm run deploy");
|
||||
});
|
||||
|
||||
it("checks out the exact dispatched revision before deploying", () => {
|
||||
expect(deploy).toContain("ref: ${{ github.sha }}");
|
||||
expect(deploy).toContain('--expected-revision "$GITHUB_SHA"');
|
||||
|
||||
Reference in New Issue
Block a user