-
Notifications
You must be signed in to change notification settings - Fork 0
feat: generate and serve OpenAPI/Swagger spec (#55) #121
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
107e105
ad104e1
003d251
a162aa5
990d26d
09c92b5
eed2011
e2f97a1
6872341
6deaab0
3f450a3
6f8aae5
4e40123
13f653f
fce8fae
4b7174f
6d321a6
8954f8f
f1c421f
9781526
593309f
1cdc247
df573f7
ca4f2d3
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 |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| # Usage: sync-chart-appversion.sh <engine-version> | ||
| # Example: sync-chart-appversion.sh 0.4.1 | ||
|
|
||
| ENGINE_VERSION="$1" | ||
| CHART_FILE="packages/helm-chart/Chart.yaml" | ||
|
|
||
| if [[ ! -f "$CHART_FILE" ]]; then | ||
| echo "ERROR: $CHART_FILE not found" | ||
| exit 1 | ||
| fi | ||
|
|
||
| sed -i "s/^appVersion:.*/appVersion: \"${ENGINE_VERSION}\"/" "$CHART_FILE" | ||
| echo "Updated $CHART_FILE appVersion to $ENGINE_VERSION" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| name: Release Engine | ||
|
|
||
| on: | ||
| push: | ||
| tags: | ||
| - 'engine/v*' | ||
|
|
||
| permissions: | ||
| contents: write | ||
| packages: write | ||
|
|
||
| jobs: | ||
| release: | ||
| name: Build and Release | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - uses: actions/setup-go@v5 | ||
| with: | ||
| go-version: '1.25' | ||
|
|
||
| - name: Log in to GHCR | ||
| uses: docker/login-action@v3 | ||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - uses: docker/setup-buildx-action@v3 | ||
|
|
||
| - name: Set goreleaser tag | ||
| run: | | ||
| # Strip "engine/" prefix so goreleaser sees a clean semver tag | ||
| TAG="${GITHUB_REF#refs/tags/engine/}" | ||
| echo "GORELEASER_CURRENT_TAG=${TAG}" >> "$GITHUB_ENV" | ||
|
|
||
| - name: Run goreleaser | ||
| uses: goreleaser/goreleaser-action@v6 | ||
| with: | ||
| version: '~> v2' | ||
| args: release --clean | ||
| workdir: packages/engine | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| trivy: | ||
| name: Trivy Scan | ||
| runs-on: ubuntu-latest | ||
| needs: release | ||
| steps: | ||
| - name: Extract version | ||
| id: vars | ||
| run: | | ||
| TAG="${GITHUB_REF#refs/tags/engine/v}" | ||
| echo "version=${TAG}" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Run Trivy vulnerability scanner | ||
| uses: aquasecurity/trivy-action@0.28.0 | ||
| with: | ||
| image-ref: "ghcr.io/dvflw/mantle:${{ steps.vars.outputs.version }}" | ||
| format: table | ||
| exit-code: '1' | ||
| severity: CRITICAL,HIGH |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| name: Release Helm Chart | ||
|
|
||
| on: | ||
| push: | ||
| tags: | ||
| - 'helm-chart/v*' | ||
|
|
||
| permissions: | ||
| contents: write | ||
| packages: write | ||
|
|
||
| jobs: | ||
| publish: | ||
| name: Package and Publish | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - uses: azure/setup-helm@v4 | ||
|
|
||
| - name: Log in to GHCR | ||
| run: echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io --username ${{ github.actor }} --password-stdin | ||
|
|
||
| - name: Extract version | ||
| id: vars | ||
| run: | | ||
| TAG="${GITHUB_REF#refs/tags/helm-chart/v}" | ||
| echo "version=${TAG}" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Package chart | ||
| run: helm package packages/helm-chart/ | ||
|
|
||
| - name: Push to OCI registry | ||
| run: helm push mantle-${{ steps.vars.outputs.version }}.tgz oci://ghcr.io/dvflw/helm-charts | ||
|
|
||
| - name: Create GitHub Release | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| TAG: ${{ github.ref_name }} | ||
| VERSION: ${{ steps.vars.outputs.version }} | ||
| run: | | ||
| gh release create "${TAG}" \ | ||
| --title "Helm Chart ${VERSION}" \ | ||
| --notes "Published to \`oci://ghcr.io/dvflw/helm-charts/mantle:${VERSION}\` | ||
|
|
||
| Install with: | ||
| \`\`\`bash | ||
| helm install mantle oci://ghcr.io/dvflw/helm-charts/mantle --version ${VERSION} | ||
| \`\`\`" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| name: Release Please | ||
|
|
||
| on: | ||
| push: | ||
| branches: [main] | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: false | ||
|
|
||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
|
|
||
| jobs: | ||
| version: | ||
| name: Version Packages | ||
| runs-on: ubuntu-latest | ||
| # Skip if this push is the Version PR merge itself (prevents loop) | ||
| if: "!startsWith(github.event.head_commit.message, 'ci: version packages')" | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - uses: oven-sh/setup-bun@v2 | ||
|
|
||
| - run: bun install --frozen-lockfile | ||
|
|
||
| - name: Create or update Version PR | ||
| uses: changesets/action@v1 | ||
| with: | ||
| version: bun run version | ||
| commit: "ci: version packages" | ||
| title: "ci: version packages" | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| name: Release Tags | ||
|
|
||
| on: | ||
| push: | ||
| branches: [main] | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: false | ||
|
|
||
| permissions: | ||
| contents: write | ||
|
|
||
| jobs: | ||
| tag: | ||
| name: Create Package Tags | ||
| runs-on: ubuntu-latest | ||
| # Only run on Version PR merges | ||
| if: "startsWith(github.event.head_commit.message, 'ci: version packages')" | ||
|
Comment on lines
+18
to
+19
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. Use the push base instead of Line 19 only works for one commit-message shape, and Lines 33-50 only compare the last parent commit. Merge commits, rebase merges, or multi-commit pushes from the version PR can therefore miss real version bumps and skip tagging entirely. Compare against 🛠️ Safer version-base detection- # Only run on Version PR merges
- if: "startsWith(github.event.head_commit.message, 'ci: version packages')"
steps:
- uses: actions/checkout@v4
with:
- fetch-depth: 2
+ fetch-depth: 0
@@
- ENGINE_OLD=$(git show HEAD~1:packages/engine/package.json 2>/dev/null | jq -r '.version' 2>/dev/null || echo "")
+ ENGINE_OLD=$(git show "${{ github.event.before }}:packages/engine/package.json" 2>/dev/null | jq -r '.version' 2>/dev/null || echo "")
@@
- HELM_OLD=$(git show HEAD~1:packages/helm-chart/package.json 2>/dev/null | jq -r '.version' 2>/dev/null || echo "")
+ HELM_OLD=$(git show "${{ github.event.before }}:packages/helm-chart/package.json" 2>/dev/null | jq -r '.version' 2>/dev/null || echo "")
@@
- SITE_OLD=$(git show HEAD~1:packages/site/package.json 2>/dev/null | jq -r '.version' 2>/dev/null || echo "")
+ SITE_OLD=$(git show "${{ github.event.before }}:packages/site/package.json" 2>/dev/null | jq -r '.version' 2>/dev/null || echo "")Also applies to: 21-61 🤖 Prompt for AI Agents |
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 2 | ||
|
|
||
| - name: Detect version bumps | ||
| id: bumps | ||
| run: | | ||
| ENGINE_BUMPED=false | ||
| HELM_BUMPED=false | ||
| SITE_BUMPED=false | ||
|
|
||
| # Check engine version bump | ||
| ENGINE_OLD=$(git show HEAD~1:packages/engine/package.json 2>/dev/null | jq -r '.version' 2>/dev/null || echo "") | ||
| ENGINE_NEW=$(jq -r '.version' packages/engine/package.json) | ||
| if [[ -n "$ENGINE_OLD" && "$ENGINE_OLD" != "$ENGINE_NEW" ]]; then | ||
| echo "Engine version bumped: $ENGINE_OLD -> $ENGINE_NEW" | ||
| ENGINE_BUMPED=true | ||
| fi | ||
|
|
||
| # Check helm-chart version bump | ||
| HELM_OLD=$(git show HEAD~1:packages/helm-chart/package.json 2>/dev/null | jq -r '.version' 2>/dev/null || echo "") | ||
| HELM_NEW=$(jq -r '.version' packages/helm-chart/package.json) | ||
| if [[ -n "$HELM_OLD" && "$HELM_OLD" != "$HELM_NEW" ]]; then | ||
| echo "Helm chart version bumped: $HELM_OLD -> $HELM_NEW" | ||
| HELM_BUMPED=true | ||
| fi | ||
|
|
||
| # Check site version bump | ||
| SITE_OLD=$(git show HEAD~1:packages/site/package.json 2>/dev/null | jq -r '.version' 2>/dev/null || echo "") | ||
| SITE_NEW=$(jq -r '.version' packages/site/package.json) | ||
| if [[ -n "$SITE_OLD" && "$SITE_OLD" != "$SITE_NEW" ]]; then | ||
| echo "Site version bumped: $SITE_OLD -> $SITE_NEW" | ||
| SITE_BUMPED=true | ||
| fi | ||
|
|
||
| echo "engine_bumped=${ENGINE_BUMPED}" >> "$GITHUB_OUTPUT" | ||
| echo "engine_version=${ENGINE_NEW}" >> "$GITHUB_OUTPUT" | ||
| echo "helm_bumped=${HELM_BUMPED}" >> "$GITHUB_OUTPUT" | ||
| echo "helm_version=${HELM_NEW}" >> "$GITHUB_OUTPUT" | ||
| echo "site_bumped=${SITE_BUMPED}" >> "$GITHUB_OUTPUT" | ||
| echo "site_version=${SITE_NEW}" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Sync Chart.yaml appVersion | ||
| if: steps.bumps.outputs.engine_bumped == 'true' | ||
| run: | | ||
| .github/scripts/sync-chart-appversion.sh "${{ steps.bumps.outputs.engine_version }}" | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| git add packages/helm-chart/Chart.yaml | ||
| git commit -m "ci: sync Chart.yaml appVersion to ${{ steps.bumps.outputs.engine_version }}" | ||
| git push | ||
|
|
||
| - name: Create and push tags | ||
| run: | | ||
| TAGGED="" | ||
|
|
||
| if [[ "${{ steps.bumps.outputs.engine_bumped }}" == "true" ]]; then | ||
| git tag "engine/v${{ steps.bumps.outputs.engine_version }}" | ||
| TAGGED="$TAGGED engine/v${{ steps.bumps.outputs.engine_version }}" | ||
| fi | ||
|
|
||
| if [[ "${{ steps.bumps.outputs.helm_bumped }}" == "true" ]]; then | ||
| git tag "helm-chart/v${{ steps.bumps.outputs.helm_version }}" | ||
| TAGGED="$TAGGED helm-chart/v${{ steps.bumps.outputs.helm_version }}" | ||
| fi | ||
|
|
||
| if [[ "${{ steps.bumps.outputs.site_bumped }}" == "true" ]]; then | ||
| git tag "site/v${{ steps.bumps.outputs.site_version }}" | ||
| TAGGED="$TAGGED site/v${{ steps.bumps.outputs.site_version }}" | ||
| fi | ||
|
|
||
| if [[ -n "$TAGGED" ]]; then | ||
| echo "Pushing tags:$TAGGED" | ||
| git push origin --tags | ||
| else | ||
| echo "No version bumps detected" | ||
| fi | ||
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:
In GitHub Actions, do job-levelpermissionsapply to all steps (including third-party actions), and is splitting write actions into a separate job the recommended least-privilege pattern?💡 Result:
Yes, job-level permissions in GitHub Actions apply to all steps within that job, including third-party actions, as they all inherit the job's GITHUB_TOKEN permissions. Yes, splitting jobs so that those requiring write permissions are separate from read-only jobs (especially those using third-party actions) is a recommended least-privilege security pattern to minimize blast radius if an action is compromised.
Citations:
🏁 Script executed:
Repository: dvflw/mantle
Length of output: 104
🏁 Script executed:
Repository: dvflw/mantle
Length of output: 3316
🌐 Web query:
GitHub Actions needs context syntax needs.job_id.outcome vs result💡 Result:
In GitHub Actions, the needs context provides access to the status of prerequisite jobs specified in the needs key of a job. The syntax is needs.<job_id>.result, where <job_id> is the ID of the dependent job (e.g., needs.build.result). - needs.<job_id>.result: The final result of the dependent job after applying continue-on-error (possible values: success, failure, cancelled, skipped). This corresponds to the job's "conclusion". There is no needs.<job_id>.outcome property documented in the official GitHub Actions contexts reference. The term "outcome" is used for steps (e.g., steps.<step_id>.outcome is the raw result before continue-on-error), but not for jobs in the needs context. The job context (for the current job) contains job.status (e.g., in_progress, completed) but no outcome or result properties matching the query. For dependent jobs, use needs.<job_id>.result. Example usage in a workflow: jobs: build: runs-on: ubuntu-latest # ... steps ... test: runs-on: ubuntu-latest needs: build if: ${{ needs.build.result == 'success' }} # ... steps ... Note: An open issue notes that needs.<job_id>.result uses the conclusion (post-continue-on-error), not raw outcome, which may be relevant for continue-on-error: true jobs.
Citations:
Limit write token scope to a dedicated follow-up job
Line 28 grants
pull-requests: writeto the entireclaudejob, which also runs a third-party action (Line 40). This unnecessarily expands write-token exposure. Keep this job read-only and move the CodeRabbit comment step into a second job with onlypull-requests: write.Suggested refactor
jobs: claude: if: | (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude') && (github.event.comment.user.login == github.repository_owner || github.event.comment.author_association == 'OWNER' || github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'COLLABORATOR')) || (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude') && (github.event.comment.user.login == github.repository_owner || github.event.comment.author_association == 'OWNER' || github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'COLLABORATOR')) || (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude') && (github.event.review.user.login == github.repository_owner || github.event.review.author_association == 'OWNER' || github.event.review.author_association == 'MEMBER' || github.event.review.author_association == 'COLLABORATOR')) || (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')) && (github.event.issue.user.login == github.repository_owner || github.event.issue.author_association == 'OWNER' || github.event.issue.author_association == 'MEMBER' || github.event.issue.author_association == 'COLLABORATOR')) runs-on: ubuntu-latest timeout-minutes: 30 permissions: contents: read - pull-requests: write + pull-requests: read issues: read id-token: write actions: read steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 1 - name: Run Claude Code id: claude uses: anthropics/claude-code-action@094bd24d575e7b30ac1576024817bf1a97c81262 # v1 with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} additional_permissions: | actions: read - - name: Request CodeRabbit re-review - if: >- - steps.claude.outcome == 'success' && ( - github.event.issue.pull_request || - github.event_name == 'pull_request_review_comment' || - github.event_name == 'pull_request_review' - ) - env: - GH_TOKEN: ${{ github.token }} - PR_NUMBER: >- - ${{ - github.event.issue.number || - github.event.pull_request.number - }} - run: | - gh pr comment "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" \ - --body "@coderabbitai review" + + request-coderabbit-review: + needs: claude + if: >- + needs.claude.result == 'success' && ( + github.event.issue.pull_request || + github.event_name == 'pull_request_review_comment' || + github.event_name == 'pull_request_review' + ) + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: Request CodeRabbit re-review + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: >- + ${{ + github.event.issue.number || + github.event.pull_request.number + }} + run: | + gh pr comment "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" \ + --body "@coderabbitai review"🤖 Prompt for AI Agents