Skip to content

ci(release): authenticate semantic-release via Flanksource GitHub App - #323

Merged
moshloop merged 4 commits into
masterfrom
fix/release-github-app-auth
Jul 28, 2026
Merged

ci(release): authenticate semantic-release via Flanksource GitHub App#323
moshloop merged 4 commits into
masterfrom
fix/release-github-app-auth

Conversation

@moshloop

@moshloop moshloop commented Jun 29, 2026

Copy link
Copy Markdown
Member

Problem

The Create Release workflow has been failing on push to master — the semantic-release job dies at job setup with Repository access blocked, and the default GITHUB_TOKEN cannot push release tags / create releases under current org policy. As a result no semver tag is cut (latest release is still v1.53.1, even though master carries newer commits such as the HAR body-key redaction feature).

This blocks downstream consumers that need a tagged release of those commits (e.g. har.HARConfig.RedactedBodyKeys).

Change

Mint a GitHub App installation token via actions/create-github-app-token@v3.2.0 from the Flanksource App credentials (FLANKSOURCE_APP_ID / FLANKSOURCE_APP_SECRET) and use it for both the checkout and the semantic-release step, replacing secrets.GITHUB_TOKEN.

Notes / follow-ups

  • Assumes FLANKSOURCE_APP_ID and FLANKSOURCE_APP_SECRET are available as repo/org secrets and the App is installed on flanksource/commons with contents: write. If APP_ID is stored as a variable instead, change secrets.FLANKSOURCE_APP_IDvars.FLANKSOURCE_APP_ID.
  • The bump-clients and hx-upload-release jobs still use secrets.FLANKBOT / secrets.GITHUB_TOKEN; left unchanged since they only run after a release is published. Can be migrated to the App token in a follow-up if FLANKBOT is also being retired.

Summary by CodeRabbit

  • Chores
    • Improved the release process to publish releases/tags using a GitHub App installation token for better reliability under organization policies.
  • New Features
    • Added a new configuration merging utility to apply overrides and perform deep cloning with policy controls.
  • Bug Fixes
    • Improved pattern matching by normalizing comma-separated include/exclude patterns (including trimming and URL-encoded commas) and handling empty normalized patterns correctly.
  • Tests
    • Updated HTTP tests to use an in-process server instead of an external service.
    • Added comprehensive tests for the new configuration merging utility.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@moshloop, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 29 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7e4fc752-a33f-47d8-9b43-05acf47ef709

📥 Commits

Reviewing files that changed from the base of the PR and between 1b42b51 and 0568694.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (6)
  • collections/slice.go
  • collections/slice_test.go
  • go.mod
  • http/http_test.go
  • merge/merge.go
  • merge/merge_test.go

Walkthrough

The changes add policy-driven configuration merging, comma-separated pattern normalization, local HTTP test isolation, a GitHub App token for releases, and the mergo dependency.

Changes

Policy-Driven Configuration Merging

Layer / File(s) Summary
Merge policy and reflective cloning
merge/merge.go, go.mod
Adds generic cloning and merging with replace, shared-reference, custom merger, override, and validation policies.
Merge behavior coverage
merge/merge_test.go
Tests defaults, explicit zero values, deep-copy behavior, shared references, custom mergers, nil destinations, and invalid policies.

Pattern Matching Normalization

Layer / File(s) Summary
Normalized pattern matching
collections/slice.go, collections/slice_test.go
Expands comma-separated patterns, trims and decodes tokens, skips empty parts, and validates matching and exclusion behavior.

HTTP Test Isolation

Layer / File(s) Summary
Local header test server
http/http_test.go
Replaces external httpbin.org requests with a local JSON-echo httptest server.

Release Workflow Token Update

Layer / File(s) Summary
GitHub App token minting and wiring
.github/workflows/release.yml
Generates a GitHub App installation token and uses it for checkout and semantic-release operations.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Accurately summarizes the main workflow change: semantic-release now uses a Flanksource GitHub App token.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/release-github-app-auth
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/release-github-app-auth

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown

Gavel summary

Source Pass Fail Skip Duration
collections 60 0 0 3.1s
files 41 0 0 65ms
github.com/flanksource/commons/certs 4 0 0 440ms
github.com/flanksource/commons/cmd/hx 8 0 0 -
github.com/flanksource/commons/cmd/hx/parse 26 0 0 -
github.com/flanksource/commons/collections/syncmap 10 0 0 -
github.com/flanksource/commons/context 1 0 0 -
github.com/flanksource/commons/duration 2 0 0 -
github.com/flanksource/commons/files 16 0 0 -
github.com/flanksource/commons/har 30 0 0 -
github.com/flanksource/commons/hash 13 0 0 -
github.com/flanksource/commons/http 95 0 2 12.7s
github.com/flanksource/commons/logger 49 0 0 -
github.com/flanksource/commons/logger/httpretty/internal/color 15 0 0 -
github.com/flanksource/commons/logger/httpretty/internal/header 1 0 0 -
github.com/flanksource/commons/lookup 7 0 0 -
github.com/flanksource/commons/merge 28 0 0 -
github.com/flanksource/commons/test 5 0 1 50ms
github.com/flanksource/commons/text 1 0 0 -
github.com/flanksource/commons/tokenizer 3 0 0 -
logger 41 0 0 2ms
set 7 0 0 1ms

Totals: 463 passed · 0 failed · 3 skipped · 16.3s

View full results

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Around line 22-35: Add an explicit permissions block for the release
job/workflow so the default repository-scoped GITHUB_TOKEN is disabled now that
the release steps use the GitHub App token. Update the workflow around the
actions/create-github-app-token, actions/checkout, and
codfish/semantic-release-action steps to grant only the minimum permissions
needed for release, ensuring no implicit extra permissions remain available.
- Around line 22-27: The GitHub App token created in the release workflow is too
broadly scoped for this job. Update the Generate GitHub App token step to
request only repository contents access by adding the appropriate contents write
permission on the actions/create-github-app-token use, so the token is limited
to the release path. Refer to the app-token step in the release workflow and
keep the rest of the release job unchanged.
- Around line 29-31: Set actions/checkout in the release workflow to avoid
persisting the App token in the local git config. Update the checkout step in
the release job to include persist-credentials: false alongside the existing
token input, since semantic-release already uses GITHUB_TOKEN and should not
rely on credentials written by checkout. Use the actions/checkout step in
release.yml as the place to make this change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e4d9a897-d210-42fa-9256-17fd558c34aa

📥 Commits

Reviewing files that changed from the base of the PR and between 516bc6d and 33419da.

📒 Files selected for processing (1)
  • .github/workflows/release.yml

Comment on lines +22 to +27
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.FLANKSOURCE_APP_ID }}
private-key: ${{ secrets.FLANKSOURCE_APP_SECRET }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the pinned action supports permission-scoped inputs.
curl -fsSL https://raw.githubusercontent.com/actions/create-github-app-token/v3.2.0/action.yml \
  | grep -A3 -n 'permission-contents'

Repository: flanksource/commons

Length of output: 609


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,220p' .github/workflows/release.yml

Repository: flanksource/commons

Length of output: 6318


Narrow the GitHub App token to contents: write. This release job only needs repository contents access for tag and release writes, but the App token currently inherits every permission on the installation. Pass permission-contents: write here to keep the token scoped to the release path.

Proposed change
       - name: Generate GitHub App token
         id: app-token
         uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
         with:
           app-id: ${{ secrets.FLANKSOURCE_APP_ID }}
           private-key: ${{ secrets.FLANKSOURCE_APP_SECRET }}
+          permission-contents: write
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.FLANKSOURCE_APP_ID }}
private-key: ${{ secrets.FLANKSOURCE_APP_SECRET }}
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.FLANKSOURCE_APP_ID }}
private-key: ${{ secrets.FLANKSOURCE_APP_SECRET }}
permission-contents: write
🧰 Tools
🪛 zizmor (1.26.1)

[error] 24-24: dangerous use of GitHub App tokens (github-app): app token inherits blanket installation permissions

(github-app)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 22 - 27, The GitHub App token
created in the release workflow is too broadly scoped for this job. Update the
Generate GitHub App token step to request only repository contents access by
adding the appropriate contents write permission on the
actions/create-github-app-token use, so the token is limited to the release
path. Refer to the app-token step in the release workflow and keep the rest of
the release job unchanged.

Source: Linters/SAST tools

Comment thread .github/workflows/release.yml
Comment on lines 29 to +31
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
token: ${{ steps.app-token.outputs.token }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the pinned checkout action's persist-credentials default.
curl -fsSL https://raw.githubusercontent.com/actions/checkout/v4.1.6/action.yml \
  | grep -A6 -n 'persist-credentials'

Repository: flanksource/commons

Length of output: 508


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the relevant workflow section with line numbers.
sed -n '1,120p' .github/workflows/release.yml | cat -n

# Look for how the semantic-release action is configured.
rg -n "semantic-release-action|GITHUB_TOKEN|app-token|persist-credentials|checkout@" .github/workflows/release.yml

Repository: flanksource/commons

Length of output: 6133


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the checkout action's documented behavior and the release workflow's surrounding steps.
python3 - <<'PY'
from pathlib import Path
p = Path('.github/workflows/release.yml')
text = p.read_text()
for i, line in enumerate(text.splitlines(), 1):
    if 1 <= i <= 120:
        print(f"{i:4d}: {line}")
PY

Repository: flanksource/commons

Length of output: 5284


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,120p' .github/workflows/release.yml | cat -n
rg -n "semantic-release-action|GITHUB_TOKEN|app-token|persist-credentials|checkout@" .github/workflows/release.yml

Repository: flanksource/commons

Length of output: 6133


🌐 Web query:

codfish/semantic-release-action GITHUB_TOKEN checkout persist-credentials false git push authentication

💡 Result:

When using plugins like @semantic-release/git in GitHub Actions, setting persist-credentials: false in the actions/checkout step is a necessary configuration to allow semantic-release to use a custom authentication token [1][2][3]. By default, actions/checkout automatically populates the local git configuration with the repository's default GITHUB_TOKEN [4][1]. If you need to perform git operations that the default token cannot handle—such as pushing to a protected branch—you must provide a custom token (e.g., a Personal Access Token or a GitHub App token) [5][6][7]. If persist-credentials is left at its default value (true), the actions/checkout step will persist the default GITHUB_TOKEN in the local git config, which takes precedence and causes your custom authentication to be ignored [4][2][7]. Setting it to false prevents this, ensuring that git uses the credentials you explicitly provide in your environment variables or configuration for semantic-release [6][7]. For secure implementations on protected branches, official documentation and community best practices recommend using a GitHub App token rather than a Personal Access Token (PAT) [8][7]. GitHub App tokens provide fine-grained permissions and short-lived credentials, which are more secure than long-lived PATs [7]. Summary of the required configuration: - In your GitHub Actions workflow, set persist-credentials: false in the actions/checkout step [1][2]. - Use a custom token (via GitHub App or PAT) with appropriate permissions for pushing [6][7]. - Pass this token to semantic-release via the GITHUB_TOKEN environment variable [4][6].

Citations:


Set persist-credentials: false on checkout. actions/checkout writes the App token into .git/config by default; semantic-release already gets the same token via GITHUB_TOKEN, so there’s no need to persist it here. .github/workflows/release.yml:29-35

🧰 Tools
🪛 zizmor (1.26.1)

[warning] 29-31: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 29 - 31, Set actions/checkout in
the release workflow to avoid persisting the App token in the local git config.
Update the checkout step in the release job to include persist-credentials:
false alongside the existing token input, since semantic-release already uses
GITHUB_TOKEN and should not rely on credentials written by checkout. Use the
actions/checkout step in release.yml as the place to make this change.

Source: Linters/SAST tools

moshloop added 2 commits July 28, 2026 12:35
…eader tests

Gavel-Issue-Id: 2a55fc284b25da73528b29fa26876212
Claude-Session-Id: c6e82086-2045-406c-87b9-b03ac8b55bf1
Add structural deep-copy config merging with Replace, Shared, and Merger policies.
Expand match filters to support comma-separated, trimmed, URL-decoded patterns while preserving exclusions.
Add focused coverage for merge precedence, aliasing, custom mergers, and pattern handling.
@moshloop
moshloop force-pushed the fix/release-github-app-auth branch from 1b42b51 to 3e12357 Compare July 28, 2026 09:35
@socket-security

socket-security Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addeddario.cat/​mergo@​v1.0.298100100100100

View full report

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@collections/slice.go`:
- Around line 131-149: Prevent exclusion-only checks from re-splitting decoded
patterns: update the logic in collections/slice.go lines 131-149 and 175-182 to
use already-normalized patterns or retain raw patterns for the final check,
preserving "!A%2CB" as one exclusion. Add regression assertions in
collections/slice_test.go lines 44-50 and 54-64 verifying MatchItems returns
true and MatchItem returns true with negated false for that input.

In `@merge/merge.go`:
- Around line 119-125: Update cloneValue to maintain a visited-reference table
keyed by pointer/map identity and reuse the previously created clone when
revisiting a reference, registering each destination before recursively cloning
its contents. Ensure both Apply and Clone handle cyclic graphs without recursion
overflow, and add a regression test using a self-referential node.
- Around line 90-92: Replace panic-based handling in Apply/Clone, the internal
policy validators, and the mergo merge path with explicit error returns;
propagate invalid policy and unsupported-input errors through their callers.
Update affected tests to assert returned errors rather than process panics,
while preserving successful merge behavior.
- Around line 185-200: Update policyTransformer.Transformer to handle
non-settable existing map entries by copying each destination into a settable
temporary, applying the Replace/Shared assignment or Merge method there, then
writing the result back via SetMapIndex. Preserve current behavior for ordinary
settable destinations, and add coverage for existing map entries under
Replace/Shared and Merger policies.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3a7f8ce0-34da-4a3b-9472-b87f6e866bdb

📥 Commits

Reviewing files that changed from the base of the PR and between 33419da and 1b42b51.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (6)
  • collections/slice.go
  • collections/slice_test.go
  • go.mod
  • http/http_test.go
  • merge/merge.go
  • merge/merge_test.go

Comment thread collections/slice.go
Comment thread merge/merge.go
Comment on lines +90 to +92
if err := mergo.Merge(&out, src, opts...); err != nil {
panic(fmt.Sprintf("merge %T: %v", base, err))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Return validation and merge errors instead of panicking.

Invalid policy entries and unsupported merge inputs currently terminate the caller process. Make Apply/Clone and the internal policy validators return errors, then update the panic tests to assert those errors. As per coding guidelines, "**/*.go: Use explicit error returns rather than panics."

Also applies to: 225-231, 244-245

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@merge/merge.go` around lines 90 - 92, Replace panic-based handling in
Apply/Clone, the internal policy validators, and the mergo merge path with
explicit error returns; propagate invalid policy and unsupported-input errors
through their callers. Update affected tests to assert returned errors rather
than process panics, while preserving successful merge behavior.

Source: Coding guidelines

Comment thread merge/merge.go
Comment thread merge/merge.go
moshloop added 2 commits July 28, 2026 12:46
Add reflection-based configuration layering with deep cloning, policy-driven replacement/shared/merger handling, and tagged slice accumulation. Normalize match patterns to support comma-separated, trimmed, URL-decoded includes and exclusions while preserving exclusion precedence. Improve HTTP test failure handling and refresh the Mergo dependency.
…graphs

Keep encoded commas literal in exclusion patterns and prevent recursive configuration graphs from overflowing the stack. Apply merge policies consistently to map entries while preserving shared references and aliasing. Remove the obsolete external-header test helper.
@moshloop
moshloop merged commit bf87bbc into master Jul 28, 2026
11 checks passed
@moshloop
moshloop deleted the fix/release-github-app-auth branch July 28, 2026 12:58
@flankbot

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.54.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants