-
Notifications
You must be signed in to change notification settings - Fork 1
docs: set up documentation site, release CI, and sandbox hardening #298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f470c4f
5d46e76
be0048f
da9de39
f0e0805
312073a
3682b0b
7c3e8ab
e128f25
ae56715
7e8f2f2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -51,6 +51,8 @@ jobs: | |
| contents: read | ||
| packages: write | ||
| id-token: write | ||
| outputs: | ||
| digest: ${{ steps.push.outputs.digest }} | ||
| steps: | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | ||
| with: | ||
|
|
@@ -103,7 +105,7 @@ jobs: | |
| format: table | ||
| exit-code: "1" | ||
| severity: CRITICAL | ||
| trivyignores: .trivyignore.yaml | ||
| trivyignores: .github/.trivyignore.yaml | ||
|
|
||
| - name: Trivy scan (high — warn only) | ||
| uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0 | ||
|
|
@@ -113,15 +115,15 @@ jobs: | |
| format: table | ||
| exit-code: "0" | ||
| severity: HIGH | ||
| trivyignores: .trivyignore.yaml | ||
| trivyignores: .github/.trivyignore.yaml | ||
|
|
||
| - name: Grype scan | ||
| uses: anchore/scan-action@7037fa011853d5a11690026fb85feee79f4c946c # v7.3.2 | ||
| with: | ||
| image: ${{ steps.scan-ref.outputs.ref }} | ||
| fail-build: true | ||
| severity-cutoff: critical | ||
| config: .grype.yaml | ||
| config: .github/.grype.yaml | ||
|
|
||
| # Push only after scans pass — prevents publishing vulnerable images. | ||
| # NOTE: This is a separate build invocation from the scan step. GHA cache | ||
|
|
@@ -162,6 +164,8 @@ jobs: | |
| contents: read | ||
| packages: write | ||
| id-token: write | ||
| outputs: | ||
| digest: ${{ steps.push.outputs.digest }} | ||
| steps: | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | ||
| with: | ||
|
|
@@ -214,7 +218,7 @@ jobs: | |
| format: table | ||
| exit-code: "1" | ||
| severity: CRITICAL | ||
| trivyignores: .trivyignore.yaml | ||
| trivyignores: .github/.trivyignore.yaml | ||
|
|
||
| - name: Trivy scan (high — warn only) | ||
| uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0 | ||
|
|
@@ -224,15 +228,15 @@ jobs: | |
| format: table | ||
| exit-code: "0" | ||
| severity: HIGH | ||
| trivyignores: .trivyignore.yaml | ||
| trivyignores: .github/.trivyignore.yaml | ||
|
|
||
| - name: Grype scan | ||
| uses: anchore/scan-action@7037fa011853d5a11690026fb85feee79f4c946c # v7.3.2 | ||
| with: | ||
| image: ${{ steps.scan-ref.outputs.ref }} | ||
| fail-build: true | ||
| severity-cutoff: critical | ||
| config: .grype.yaml | ||
| config: .github/.grype.yaml | ||
|
|
||
| # Push only after scans pass — prevents publishing vulnerable images. | ||
| # NOTE: Separate build invocation; GHA cache ensures deterministic layers, | ||
|
|
@@ -263,3 +267,74 @@ jobs: | |
| exit 1 | ||
| fi | ||
| cosign sign --yes ghcr.io/aureliolo/synthorg-web@${DIGEST} | ||
|
|
||
| # Append container image references to the GitHub Release (version tags only) | ||
| update-release: | ||
| name: Update Release Notes | ||
| if: startsWith(github.ref, 'refs/tags/v') | ||
| needs: [version, build-backend, build-web] | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: write | ||
| steps: | ||
| - name: Append container images to release | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| GH_REPO: ${{ github.repository }} | ||
| TAG: ${{ github.ref_name }} | ||
| VERSION: ${{ needs.version.outputs.app_version }} | ||
| BACKEND_DIGEST: ${{ needs.build-backend.outputs.digest }} | ||
| WEB_DIGEST: ${{ needs.build-web.outputs.digest }} | ||
| run: | | ||
| set -euo pipefail | ||
|
|
||
| # Validate required inputs | ||
| if [ -z "$VERSION" ] || [ -z "$BACKEND_DIGEST" ] || [ -z "$WEB_DIGEST" ]; then | ||
| echo "::error::Missing required values: VERSION='$VERSION' BACKEND_DIGEST='$BACKEND_DIGEST' WEB_DIGEST='$WEB_DIGEST'" | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Bounded retry — Release Please may still be creating the release | ||
| EXISTING="" | ||
| for i in $(seq 1 6); do | ||
| if EXISTING=$(gh release view "$TAG" --json body -q '.body // ""' 2>/dev/null); then | ||
| break | ||
| fi | ||
| echo "Release '$TAG' not available yet (attempt $i/6), retrying in 10s..." | ||
| sleep 10 | ||
| done | ||
|
Comment on lines
+298
to
+305
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No explicit failure path after retry exhaustion If all 6 attempts to find the release fail, the loop exits with Consider adding an explicit check after the loop using a success flag: Without this, you cannot distinguish between "release found with empty body" and "release never found" from the value of Prompt To Fix With AIThis is a comment left during a code review.
Path: .github/workflows/docker.yml
Line: 298-305
Comment:
**No explicit failure path after retry exhaustion**
If all 6 attempts to find the release fail, the loop exits with `EXISTING=""` (its initial value) and execution continues silently. The only failure point is the subsequent `gh release edit "$TAG"` call, which fails with a generic "could not find release" message rather than a clear "exhausted retries" diagnostic.
Consider adding an explicit check after the loop using a success flag:
```
EXISTING=""
RELEASE_FOUND=false
for i in $(seq 1 6); do
if EXISTING=$(gh release view "$TAG" --json body -q '.body // ""' 2>/dev/null); then
RELEASE_FOUND=true
break
fi
echo "Release '$TAG' not available yet (attempt $i/6), retrying in 10s..."
sleep 10
done
if [ "$RELEASE_FOUND" = "false" ]; then
echo "::error::Release '$TAG' not found after 6 retries — cannot append container images"
exit 1
fi
```
Without this, you cannot distinguish between "release found with empty body" and "release never found" from the value of `EXISTING` alone, since both cases leave it as `""`.
How can I resolve this? If you propose a fix, please make it concise. |
||
|
|
||
| IMAGES=$(cat <<'BLOCK' | ||
|
|
||
| ## Container Images | ||
|
|
||
| | Image | Pull | | ||
| |-------|------| | ||
| | Backend | `docker pull ghcr.io/aureliolo/synthorg-backend:VERSION_PH` | | ||
| | Web | `docker pull ghcr.io/aureliolo/synthorg-web:VERSION_PH` | | ||
|
|
||
| **Digests** (for pinning): | ||
| - Backend: `ghcr.io/aureliolo/synthorg-backend@BACKEND_DIGEST_PH` | ||
| - Web: `ghcr.io/aureliolo/synthorg-web@WEB_DIGEST_PH` | ||
|
|
||
| All images are signed with [cosign](https://github.com/sigstore/cosign). Verify with: | ||
| ```bash | ||
| cosign verify ghcr.io/aureliolo/synthorg-backend@BACKEND_DIGEST_PH \ | ||
| --certificate-identity-regexp='github\.com/Aureliolo/synthorg' \ | ||
| --certificate-oidc-issuer='https://token.actions.githubusercontent.com' | ||
|
|
||
| cosign verify ghcr.io/aureliolo/synthorg-web@WEB_DIGEST_PH \ | ||
| --certificate-identity-regexp='github\.com/Aureliolo/synthorg' \ | ||
| --certificate-oidc-issuer='https://token.actions.githubusercontent.com' | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| ``` | ||
|
greptile-apps[bot] marked this conversation as resolved.
|
||
| BLOCK | ||
| ) | ||
| # Dedent (remove leading 10-space YAML indentation) and substitute placeholders | ||
| IMAGES=$(echo "$IMAGES" | sed 's/^ //') | ||
| IMAGES=${IMAGES//VERSION_PH/$VERSION} | ||
| IMAGES=${IMAGES//BACKEND_DIGEST_PH/$BACKEND_DIGEST} | ||
| IMAGES=${IMAGES//WEB_DIGEST_PH/$WEB_DIGEST} | ||
|
|
||
| # Idempotent: strip existing Container Images section before appending | ||
| CLEANED=$(echo "$EXISTING" | sed '/^## Container Images$/,$d') | ||
| gh release edit "$TAG" --notes "${CLEANED}${IMAGES}" | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,93 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| name: GitHub Pages | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| push: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| branches: [main] | ||||||||||||||||||||||||||||||||||||||||||||||||||
| paths: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| - "docs/**" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| - "site/**" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| - "mkdocs.yml" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| - "src/ai_company/**" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| - ".github/workflows/pages.yml" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| workflow_dispatch: | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+3
to
+12
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Consider gating deployment on CI success. The workflow triggers on Consider adding a dependency on the CI workflow: 💡 Suggested workflow modification on:
push:
branches: [main]
paths:
- "docs/**"
- "site/**"
- "mkdocs.yml"
- "src/ai_company/**"
- ".github/workflows/pages.yml"
workflow_dispatch:
+ workflow_run:
+ workflows: ["CI"] # or your main CI workflow name
+ types: [completed]
+ branches: [main]Then add a condition to skip if CI failed: jobs:
build:
# Only run if triggered manually, by push, or if CI succeeded
if: >
github.event_name != 'workflow_run' ||
github.event.workflow_run.conclusion == 'success'📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| permissions: {} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| concurrency: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| group: "pages" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| cancel-in-progress: false | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| build: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if: github.ref == 'refs/heads/main' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| name: Build Site | ||||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
coderabbitai[bot] marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| contents: read | ||||||||||||||||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| persist-credentials: false | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| # --- MkDocs (documentation at /docs) --- | ||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Set up Python | ||||||||||||||||||||||||||||||||||||||||||||||||||
| uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| python-version: "3.14" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| allow-prereleases: true | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Install uv | ||||||||||||||||||||||||||||||||||||||||||||||||||
| uses: astral-sh/setup-uv@6b9c6063abd6010835644d4c2e1bef4cf5cd0fca # v6.0.1 | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Install docs dependencies | ||||||||||||||||||||||||||||||||||||||||||||||||||
| run: uv sync --group docs --no-dev | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| run: uv sync --group docs --no-dev | |
| run: uv sync --group docs --no-dev --frozen |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
Foractions/dependency-review-actionv4, does theallow-licensessetting apply globally to all dependency changes in the pull request, or can license allowances be scoped to specific packages or manifests?💡 Result:
In
actions/dependency-review-action@v4,allow-licensesis a single, global allowlist: the action will fail the PR if it introduces any dependency whose detected license doesn’t match theallow-licenseslist. There’s no built-in way to scope different license allowlists to specific packages or specific manifests. [1]If you need exceptions for particular dependencies, the v4 action provides
allow-dependencies-licenses, which lets you exclude specific packages (by purl) from license checks—but that’s package-based, not manifest-scoped. [1]Sources
[1]
actions/dependency-review-actionREADME (Configuration options forallow-licensesandallow-dependencies-licenses) (github.com)Citations:
Don't globally allow LGPL licenses in the dependency review.
The
allow-licensessetting applies globally to every dependency change in pull requests—there's no way to scope exceptions to specific packages or only build-time dependencies. Once LGPL licenses are added to this list, any future LGPL dependency will pass the check silently, even if it's a runtime or production dependency outside the intended Astro scope.Use
allow-dependencies-licensesinstead to exclude only the specific Astro packages by their package URL (purl), or move LGPL exceptions to a narrower configuration if the action supports alternative scoping mechanisms.🤖 Prompt for AI Agents