Skip to content

Commit 20a38a8

Browse files
Phase B/2: workflow audit before the first push, not after
The excalidraw lesson, applied. This repo inherited the boilerplate's workflows and had never run them; the first push would have run them against another site. (a) SCRIPTS. Every script the workflows invoke — network_smoke.py, smoke_live.py, dev.sh — exists in this tree. Nothing missing. (b) NAMES AND URLS. cd.yml carried `SITE_URL: https://boilerplate.2plot.dev` hard-coded. Unguarded, the inaugural push would have polled ANOTHER SITE's /healthz for fifteen minutes waiting for a commit it will never serve, failed, then run both live batteries against it and reported red — a fork failing CD on day one over a host it does not own. ci.yml's Docker image was still tagged `dash-docs-boilerplate:ci` ("a fork changes the matrix and the image name", which this fork had not), and its header described this repo as the template every satellite copies. Both fixed. The remaining mentions of boilerplate.2plot.dev now correctly name it as a DIFFERENT site. (c) THE LIVE HALF IS GUARDED. Everything touching a running host — the build-match wait and the whole `verify` job — is gated on the repository variable SITE_URL, with no hard-coded fallback: an empty value IS the signal that no service exists. A default would silently re-point this workflow at somebody else's host, which is the defect being fixed. Pointing it at llms.2plot.dev today would be no better — that domain still serves the OUTGOING site this migration replaces. Unguarding takes no workflow edit, twice: B3 staging — set the repo variable SITE_URL to https://<name>.onrender.com B5 cutover — change that same variable to https://llms.2plot.dev Marked B3 TODO in cd.yml's header and at both guarded sites. A dormant run now prints a notice saying exactly what is skipped and how to bring it up, so a green-but-inert CD is legible rather than mysterious. The `environment.url` is omitted rather than evaluated to an empty string: the first run in this repo's history should not hinge on how GitHub treats a blank environment URL. B3 restores it with the variable. Both workflows and dependabot.yml parse. Phase B/3: the social card is verification-only, and it verifies. OG_IMAGE_URL is exactly https://cdn.2plot.ai/github_assets/llms.2plot.dev.png; the object is live (HTTP 200, image/png, 56,587 bytes) and its real IHDR pixels are 1200x630, matching OG_IMAGE_WIDTH/HEIGHT. Nothing generated, nothing uploaded.
1 parent 194454d commit 20a38a8

2 files changed

Lines changed: 65 additions & 17 deletions

File tree

‎.github/workflows/cd.yml‎

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,37 @@
11
name: CD
22

3-
# Deploys boilerplate.2plot.dev, then checks the live site.
3+
# Deploys llms.2plot.dev, then checks the live site.
4+
#
5+
# ============================ B3 TODO =====================================
6+
# THE LIVE HALF OF THIS WORKFLOW IS DORMANT UNTIL A RENDER SERVICE EXISTS.
7+
#
8+
# Everything that touches a running host — the build-match wait and the whole
9+
# `verify` job — is gated on the repository variable `SITE_URL`. While it is
10+
# unset those steps skip with a notice and CD is effectively "CI plus an
11+
# optional deploy trigger".
12+
#
13+
# This is not caution for its own sake. The template shipped
14+
# SITE_URL=https://boilerplate.2plot.dev hard-coded, so an unguarded run here
15+
# would poll ANOTHER SITE's /healthz for fifteen minutes waiting for a commit
16+
# it will never serve, then battery it and report red — a fork failing CD on
17+
# day one over a host it does not own. (Same class as the excalidraw finding:
18+
# inherited workflows reference things that do not exist in the fork and
19+
# deploy hosts that are not yours.) Pointing it at llms.2plot.dev today is no
20+
# better: that domain still serves the OUTGOING site this migration replaces.
21+
#
22+
# TO UNGUARD, in two steps, no workflow edit either time:
23+
# B3 (staging): set the repo variable SITE_URL to the service's
24+
# https://<name>.onrender.com URL. The wait and the battery
25+
# come alive against staging.
26+
# B5 (cutover): change that same variable to https://llms.2plot.dev once
27+
# the domain moves.
28+
# ==========================================================================
429
#
530
# The deploy step POSTs to a Render deploy hook held in the
631
# RENDER_DEPLOY_HOOK_URL secret. Without that secret the step is skipped and
732
# the workflow goes straight to verification — useful when Render is already
8-
# auto-deploying from GitHub on its own, and it means a fork of this template
9-
# doesn't fail CD on day one for a secret it was never given.
33+
# auto-deploying from GitHub on its own, and it means this repo doesn't fail
34+
# CD on day one for a secret it was never given.
1035
on:
1136
push:
1237
branches: [main]
@@ -26,7 +51,10 @@ concurrency:
2651

2752
env:
2853
PIP_DISABLE_PIP_VERSION_CHECK: "1"
29-
SITE_URL: ${{ inputs.target_url || 'https://boilerplate.2plot.dev' }}
54+
# No hard-coded fallback, deliberately: an empty SITE_URL is the signal
55+
# that no service exists yet, and every live step keys off it. A default
56+
# here would silently re-point this workflow at somebody else's host.
57+
SITE_URL: ${{ inputs.target_url || vars.SITE_URL }}
3058

3159
jobs:
3260
test:
@@ -44,10 +72,19 @@ jobs:
4472
timeout-minutes: 20
4573
environment:
4674
name: production
47-
url: https://boilerplate.2plot.dev
75+
# B3 TODO: restore `url: ${{ inputs.target_url || vars.SITE_URL }}`
76+
# when SITE_URL is set. Omitted while dormant rather than evaluated to
77+
# an empty string — the deployment panel simply shows no link, and the
78+
# first run in this repo's history does not hinge on how GitHub treats
79+
# a blank environment URL.
4880
outputs:
4981
deployed: ${{ steps.hook.outputs.deployed }}
5082
steps:
83+
- name: Say plainly that the live half is dormant
84+
if: env.SITE_URL == ''
85+
run: |
86+
echo "::notice::No Render service yet — SITE_URL repo variable is unset, so the build-match wait and the live batteries are skipped. Set SITE_URL to the .onrender.com URL at B3 to bring them up (see this workflow's header)."
87+
5188
- name: Trigger the Render deploy hook
5289
id: hook
5390
env:
@@ -62,6 +99,10 @@ jobs:
6299
echo "deployed=true" >> "$GITHUB_OUTPUT"
63100
64101
- name: Wait for THIS build to serve traffic
102+
# B3 TODO: skips while SITE_URL is unset — see the header. Without
103+
# this guard the loop below polls a host this repo does not own for
104+
# fifteen minutes and then fails the run.
105+
if: env.SITE_URL != ''
65106
# NOT gated on the hook step: with RENDER_DEPLOY_HOOK_URL unset,
66107
# Render's own autoDeploy ships the commit minutes after the push —
67108
# and the old shape skipped this wait and ran the battery three
@@ -105,7 +146,12 @@ jobs:
105146
verify:
106147
name: verify the live site
107148
needs: [deploy]
108-
if: always() && needs.deploy.result != 'cancelled'
149+
# B3 TODO: the whole job is dormant until SITE_URL names a real service.
150+
# `vars.SITE_URL` rather than `env.SITE_URL` because job-level `if` is
151+
# evaluated before the job's env context exists.
152+
if: >-
153+
always() && needs.deploy.result != 'cancelled'
154+
&& (inputs.target_url || vars.SITE_URL) != ''
109155
runs-on: ubuntu-latest
110156
timeout-minutes: 15
111157
steps:

‎.github/workflows/ci.yml‎

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# CI for boilerplate.2plot.dev — and the TEMPLATE every 2plot satellite copies.
1+
# CI for llms.2plot.dev — the documentation site for dash-improve-my-llms.
22
#
3-
# This repo is the one the other documentation sites are forked from, so the
4-
# shape of this file is part of the deliverable. It implements the network's
5-
# CI baseline (2plot.ai and 2plot.dev run the same one):
3+
# Inherited from dash-documentation-boilerplate, which is where the shape of
4+
# this file is the deliverable. Here it is just the network's CI baseline
5+
# (2plot.ai and 2plot.dev run the same one):
66
#
77
# * least-privilege `permissions` and a cancel-in-progress `concurrency`
88
# group, so a workflow cannot write more than it reads and a rapid second
@@ -18,8 +18,9 @@
1818
# provable when nothing is configured;
1919
# * an advisory pip-audit.
2020
#
21-
# A fork changes the matrix and the image name. Everything else is the
22-
# standard; see the 2plot network standard on boilerplate.2plot.dev.
21+
# A fork changes the matrix and the image name — both done here. Everything
22+
# else is the standard; see the 2plot network standard on
23+
# boilerplate.2plot.dev (the template's own live site, not this one).
2324

2425
name: CI
2526

@@ -215,7 +216,7 @@ jobs:
215216
uses: docker/build-push-action@v6
216217
with:
217218
context: .
218-
tags: dash-docs-boilerplate:ci
219+
tags: llms-2plot-dev:ci
219220
load: true
220221
cache-from: type=gha
221222
cache-to: type=gha,mode=max
@@ -224,7 +225,7 @@ jobs:
224225
# are asserted here, inside the artifact that actually ships.
225226
- name: Version fingerprints inside the image
226227
run: |
227-
docker run --rm dash-docs-boilerplate:ci python -c "
228+
docker run --rm llms-2plot-dev:ci python -c "
228229
from importlib.metadata import version
229230
230231
def parts(v):
@@ -256,7 +257,7 @@ jobs:
256257
# platform loops the worker and the deploy never goes live.
257258
- name: Boot the container and wait for /healthz
258259
run: |
259-
docker run -d --name docs -p 8550:8550 dash-docs-boilerplate:ci
260+
docker run -d --name docs -p 8550:8550 llms-2plot-dev:ci
260261
for i in $(seq 1 60); do
261262
if curl -sf http://127.0.0.1:8550/healthz > /dev/null; then
262263
echo "healthy after ~$((i*2))s"
@@ -273,8 +274,9 @@ jobs:
273274
docker logs --tail 100 docs
274275
exit 1
275276
276-
# The SAME script CD runs against https://boilerplate.2plot.dev, so a
277-
# failure in CI and a failure in production read identically.
277+
# The SAME script CD runs against the live host (once B3 sets the
278+
# SITE_URL repo variable — see cd.yml's header), so a failure in CI and
279+
# a failure in production read identically.
278280
- name: Smoke battery against the booted container
279281
run: python3 scripts/network_smoke.py --base-url http://127.0.0.1:8550
280282

0 commit comments

Comments
 (0)