Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export default defineConfig({
{ label: "audit", slug: "docs/go/cli/audit" },
{ label: "validate", slug: "docs/go/cli/validate" },
{ label: "Identity Model", slug: "docs/go/concepts/identity-model" },
{ label: "Enforce in CI", slug: "docs/go/guides/enforce-in-ci" },
{ label: "Supported Scope", slug: "docs/go/reference/supported-scope" },
{ label: "Limitations", slug: "docs/go/reference/limitations" },
],
Expand Down
124 changes: 124 additions & 0 deletions src/content/docs/docs/go/guides/enforce-in-ci.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
---
title: Enforce a No-New-LaunchDarkly Policy for Go in CI
description: Use flaglint-go validate in GitHub Actions to block new direct LaunchDarkly Go SDK calls, adopting gradually via baseline mode.
lastUpdated: 2026-07-06
---

flaglint-go has no published GitHub Action (unlike flaglint-js's `flaglint/flaglint` composite action) — install it in your workflow with `go install` or Homebrew, then run `validate` directly. Both are one extra step.

## Install in CI

**Via `go install`** (needs `actions/setup-go`, already common in Go CI):

```yaml
- uses: actions/setup-go@v5
with:
go-version: '1.23'
- run: go install github.com/flaglint/flaglint-go/cmd/flaglint-go@latest
```
Comment on lines +13 to +18

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
gh api repos/flaglint/flaglint-go/releases/latest --jq '.tag_name'

Repository: flaglint/flaglint.dev

Length of output: 166


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== file outline ==\n'
git ls-files 'src/content/docs/docs/go/guides/enforce-in-ci.md'
printf '\n== relevant lines ==\n'
nl -ba src/content/docs/docs/go/guides/enforce-in-ci.md | sed -n '1,140p'

printf '\n== release tag already known ==\n'
gh api repos/flaglint/flaglint-go/releases/latest --jq '.tag_name'

Repository: flaglint/flaglint.dev

Length of output: 290


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '== file lines 1-140 ==\n'
sed -n '1,140p' src/content/docs/docs/go/guides/enforce-in-ci.md

printf '\n== occurrences of go install ==\n'
grep -n "go install" -n src/content/docs/docs/go/guides/enforce-in-ci.md || true

printf '\n== latest release tag ==\n'
gh api repos/flaglint/flaglint-go/releases/latest --jq '.tag_name'

Repository: flaglint/flaglint.dev

Length of output: 4611


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '== file lines 1-140 ==\n'
sed -n '1,140p' src/content/docs/docs/go/guides/enforce-in-ci.md

printf '\n== go install occurrences ==\n'
grep -n "go install" src/content/docs/docs/go/guides/enforce-in-ci.md || true

printf '\n== latest release tag ==\n'
gh api repos/flaglint/flaglint-go/releases/latest --jq '.tag_name'

Repository: flaglint/flaglint.dev

Length of output: 4608


Pin all three go install snippets to v0.1.1. Using @latest lets the documented CI flow drift as new releases land, so the examples can change behavior without a docs update.

🤖 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 `@src/content/docs/docs/go/guides/enforce-in-ci.md` around lines 13 - 18, The
documentation example still uses an unpinned go install target, so update the
flaglint-go installation snippet in the CI guide to use v0.1.1 instead of
`@latest`, and make the same version pin consistently across the other go install
snippets in this doc so the examples stay stable. Refer to the go install
commands in the CI guide and ensure each one is explicitly versioned to v0.1.1.


This is the option used in the full workflow examples below — it works the same way on every GitHub-hosted runner OS.

**Via Homebrew** — on `macos-latest`, `brew` is already on `PATH`:

```yaml
- run: brew install flaglint/tap/flaglint-go
```

On `ubuntu-latest`, Homebrew is preinstalled but **not** added to `PATH` by default — initialize it first:

```yaml
- run: |
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
brew install flaglint/tap/flaglint-go
```

## Recommended: Adopt With a Baseline First

Turning on `--no-direct-launchdarkly` immediately fails CI for every existing call site — usually not what you want on day one. Capture current debt as a baseline once, commit it, and fail only on *new* debt going forward:

```bash
# Run once, locally, and commit the result
flaglint-go audit ./services --write-baseline .flaglint-baseline.json
```

```yaml
name: FlagLint Go
on: [pull_request]

jobs:
flaglint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.23'
- run: go install github.com/flaglint/flaglint-go/cmd/flaglint-go@latest
- run: flaglint-go validate ./services --baseline .flaglint-baseline.json --fail-on-new
```

This fails the build only when a call site's fingerprint isn't already in `.flaglint-baseline.json`. Re-run `--write-baseline` (and commit the update) whenever you accept new debt on purpose or resolve existing findings.

## Blocking All Direct Calls

Once existing debt is cleared (or for a codebase starting clean), enforce the strict policy instead:

```yaml
- run: flaglint-go validate ./services --no-direct-launchdarkly
```

Do not add `continue-on-error: true` to this step — the job should fail when violations exist.

### Bootstrap Exclusions

Files that legitimately wire the LaunchDarkly client directly (a provider-setup package, for example) can be exempted:

```yaml
- run: |
flaglint-go validate ./services \
--no-direct-launchdarkly \
--bootstrap-exclude "internal/openfeature-bootstrap/**"
```

## SARIF Upload for GitHub Code Scanning

```yaml
name: FlagLint Go (SARIF)
on: [pull_request]

jobs:
validate:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.23'
- run: go install github.com/flaglint/flaglint-go/cmd/flaglint-go@latest

- name: Validate no direct LaunchDarkly Go SDK calls
run: |
flaglint-go validate ./services \
--no-direct-launchdarkly \
--format sarif \
--output flaglint-go-validation.sarif

- name: Upload SARIF
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: flaglint-go-validation.sarif
```

`if: always()` belongs on the upload step, not the validate step, so GitHub Code Scanning still ingests results even when validation fails. SARIF findings use rule ID `flaglint.go.direct-launchdarkly`.

## Feedback

- [Edit this page on GitHub](https://github.com/flaglint/flaglint.dev/edit/main/src/content/docs/docs/go/guides/enforce-in-ci.md)
- [Report an issue](https://github.com/flaglint/flaglint-go/issues/new)
- See also: [validate reference](/docs/go/cli/validate/)
- Next: [flaglint-go Overview](/docs/go/)
Loading