Skip to content

Commit e6035cd

Browse files
committed
ci: complete phase 17 delivery gates
1 parent 03584eb commit e6035cd

4 files changed

Lines changed: 147 additions & 4 deletions

File tree

.github/workflows/ci.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,17 @@ jobs:
7878

7979
- name: Build frontend production bundle
8080
run: npm run build
81+
82+
compose:
83+
name: Compose image and migration gates
84+
runs-on: ubuntu-latest
85+
needs: [backend, frontend]
86+
steps:
87+
- name: Check out source
88+
uses: actions/checkout@v6
89+
90+
- name: Validate Compose configuration
91+
run: docker compose config --quiet
92+
93+
- name: Build backend and frontend images
94+
run: docker compose build --pull backend frontend
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: Release candidate validation
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
release_tag:
7+
description: Existing semantic-version Git tag to validate, for example v1.2.3
8+
required: true
9+
type: string
10+
11+
permissions:
12+
contents: read
13+
14+
concurrency:
15+
group: release-validation-${{ inputs.release_tag }}
16+
cancel-in-progress: false
17+
18+
jobs:
19+
validate-release-candidate:
20+
name: Validate immutable release candidate
21+
runs-on: ubuntu-latest
22+
steps:
23+
- name: Validate requested release tag format
24+
env:
25+
RELEASE_TAG: ${{ inputs.release_tag }}
26+
run: |
27+
if [[ ! "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then
28+
echo "release_tag must use semantic version format such as v1.2.3" >&2
29+
exit 1
30+
fi
31+
32+
- name: Check out the requested tag
33+
uses: actions/checkout@v6
34+
with:
35+
ref: ${{ inputs.release_tag }}
36+
fetch-depth: 0
37+
38+
- name: Resolve immutable source identity
39+
id: source
40+
run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
41+
42+
- name: Build immutable backend candidate
43+
run: docker build --pull --tag "aegisai-backend:${{ steps.source.outputs.sha }}" backend
44+
45+
- name: Build immutable frontend candidate
46+
run: docker build --pull --tag "aegisai-frontend:${{ steps.source.outputs.sha }}" frontend
47+
48+
- name: Verify candidate image identities
49+
run: |
50+
docker image inspect "aegisai-backend:${{ steps.source.outputs.sha }}" > /dev/null
51+
docker image inspect "aegisai-frontend:${{ steps.source.outputs.sha }}" > /dev/null
52+
53+
- name: Publish release handoff summary
54+
env:
55+
RELEASE_TAG: ${{ inputs.release_tag }}
56+
SOURCE_SHA: ${{ steps.source.outputs.sha }}
57+
run: |
58+
echo "## AegisAI release candidate" >> "$GITHUB_STEP_SUMMARY"
59+
echo "- Git tag: \`$RELEASE_TAG\`" >> "$GITHUB_STEP_SUMMARY"
60+
echo "- Immutable source commit: \`$SOURCE_SHA\`" >> "$GITHUB_STEP_SUMMARY"
61+
echo "- Backend candidate: \`aegisai-backend:$SOURCE_SHA\`" >> "$GITHUB_STEP_SUMMARY"
62+
echo "- Frontend candidate: \`aegisai-frontend:$SOURCE_SHA\`" >> "$GITHUB_STEP_SUMMARY"
63+
echo "" >> "$GITHUB_STEP_SUMMARY"
64+
echo "No image was published and no environment was deployed by this workflow." >> "$GITHUB_STEP_SUMMARY"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Qdrant is already provisioned as local infrastructure. Phase 6 stores original d
5353
| Phase 14 — Administration control plane | Complete | Secure APIs for users, RBAC summaries, document/job operations, and operational overview. |
5454
| Phase 15 — Next.js frontend | Complete | Browser workspace, server-managed sessions, document/search/chat, administration, and full Compose verification are complete. |
5555
| Phase 16 — Observability | Complete | Privacy-safe JSON logs and request correlation, safe failure telemetry, liveness/readiness, Prometheus metrics, worker task signals, and operating guidance. |
56-
| Phase 17 — CI/CD | In progress | The delivery contract is defined; automated source, image, migration, and frontend quality gates are next. |
56+
| Phase 17 — CI/CD | Complete | GitHub Actions validates source, migrations, images, and frontend builds; manual release candidates are traceable by tag and commit without deployment authority. |
5757
| Phases 18–20 — Production scale | Planned | Kubernetes, multi-tenancy, API keys, rate limits, and retention controls. |
5858

5959
### Engineering documents

docs/ci-cd.md

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ setting, not something the repository can enable by itself.
5858

5959
- [x] 17.1 Delivery contract and trust boundaries
6060
- [x] 17.2 Backend and frontend continuous integration
61-
- [ ] 17.3 Compose image and migration validation
62-
- [ ] 17.4 Release artifact and deployment safeguards
63-
- [ ] 17.5 Workflow verification and operating guide
61+
- [x] 17.3 Compose image and migration validation
62+
- [x] 17.4 Release candidate and deployment safeguards
63+
- [x] 17.5 Workflow verification and operating guide
6464

6565
## 17.2 Continuous integration
6666

@@ -78,3 +78,68 @@ The frontend runs `tsc --noEmit` as its explicit type gate. Next's production
7878
build uses its compiler-API mode because the project-local TypeScript CLI can
7979
finish `--showConfig` before Next attaches its output listener. This avoids a
8080
false build failure while preserving independent type checking in CI.
81+
82+
## 17.3 Compose construction gate
83+
84+
The `compose` CI job runs only after the source-level backend and frontend
85+
checks pass. It validates `docker-compose.yaml` and then builds the backend and
86+
frontend images from a clean GitHub-hosted runner. The backend Dockerfile
87+
already embeds the unit-test and Alembic SQL gates, so this independently proves
88+
that the container recipe—not just a local virtual environment—remains valid.
89+
90+
The job builds images but never starts the Compose platform. That prevents CI
91+
from creating documents, contacting configured AI/SSO providers, or turning a
92+
pull request into an integration deployment.
93+
94+
## 17.4 Manual release-candidate validation
95+
96+
`release-validation.yml` is deliberately manual. An operator supplies an
97+
existing semantic-version Git tag such as `v1.2.3`; the workflow checks out
98+
that immutable reference, resolves its commit SHA, and builds candidate backend
99+
and frontend images identified by that SHA. Its run summary records the tag,
100+
commit, and candidate image identities for a release handoff.
101+
102+
It has read-only repository access and does **not** publish images, use
103+
repository secrets, deploy an environment, or mutate the Git tag. A registry,
104+
deployment environment, approval policy, rollout, and rollback design are
105+
prerequisites for a later Phase 18 deployment workflow.
106+
107+
## 17.5 Verification and operator setup
108+
109+
### Local verification
110+
111+
```bash
112+
# Validate the local platform declaration and cleanly build its two application images.
113+
docker compose config --quiet
114+
docker compose build --pull backend frontend
115+
116+
# Run the same source-level checks as CI.
117+
cd backend
118+
venv/bin/python -m unittest discover -s tests -v
119+
venv/bin/alembic upgrade head --sql > /tmp/aegis-ci-migrations.sql
120+
121+
cd ../frontend
122+
npm ci
123+
npm run typecheck
124+
npm test
125+
npm run build
126+
```
127+
128+
### GitHub setup and verification
129+
130+
1. Push the commits containing `.github/workflows/ci.yml` to the remote
131+
repository, then open a pull request or inspect the resulting push run in
132+
the **Actions** tab.
133+
2. Confirm these three checks succeed: **Backend tests and migration
134+
validation**, **Frontend type, test, and production build**, and **Compose
135+
image and migration gates**.
136+
3. In repository branch-protection settings, require all three checks before a
137+
protected-branch merge and require review for workflow-file changes.
138+
4. To prepare a release candidate, create and push an approved semantic-version
139+
Git tag, then choose **Release candidate validation** in the Actions tab and
140+
enter that exact tag. Read the resulting job summary; it is a handoff record,
141+
not a deployment.
142+
143+
GitHub validates workflow syntax and executes these jobs only after the files
144+
are pushed. The local commands above verify the application behavior and Docker
145+
construction without requiring a remote account or a production secret.

0 commit comments

Comments
 (0)