Skip to content

fix: concatenate filepattern alias contents once per alias instead of once per flag - #604

Merged
cspath1 merged 3 commits into
launchdarkly:mainfrom
Fieldguide:jaz/filepattern-alias-memory
Jul 15, 2026
Merged

fix: concatenate filepattern alias contents once per alias instead of once per flag#604
cspath1 merged 3 commits into
launchdarkly:mainfrom
Fieldguide:jaz/filepattern-alias-memory

Conversation

@jazanne

@jazanne jazanne commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Disclaimer: I used AI to generate this PR and fix - if that's not allowed please let me know.

Problem

GenerateAliases calls GenerateAliasesFromFilePattern once per flag key, and that function rebuilds the full concatenation of all glob-matched file contents (plus a []bytestring copy for the regex engine) on every call.

On a repo with ~80MB of matched source and ~160 flags, peak allocation reaches tens of GB and the process is OOM-killed (exit 137) before producing any output. The same blowup affects find-code-references-in-pull-request, which consumes this package as a library and passes all flag keys through the same path.

Fix

Hoist the concatenation out of the per-flag loop: GenerateAliases now builds each filepattern alias's contents once and reuses it across flags. GenerateAliasesFromFilePattern keeps its public signature and behavior, delegating to the extracted concatFilePatternContents + matchFilePatternAliases helpers.

With this change the same scan (~160 flags, ~80MB matched contents, alpine container) completes in ~14s with no OOM.

Testing

go test ./aliases/...

Existing suite passes unchanged; no behavior change, output is identical for the repos we compared before/after.

Prior art

#491 (for #377, "Tool gets stuck when defining glob filepattern on big repo") added glob and regex caching on this same path, which addressed the CPU side of big-repo filepattern scans. This change addresses the remaining memory side: the per-flag rebuild of the concatenated file contents.

GenerateAliases rebuilt the full concatenation of matched file contents
(plus a []byte-to-string copy) for every flag key. On a repo with ~80MB
of matched source and ~160 flags, peak allocation reached tens of GB and
the process was OOM-killed. Hoist the concatenation to GenerateAliases
and reuse it across flags.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@cspath1 cspath1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thank you for this! It looks like there's a minor lint issue with allFileContents being unused now. Approving now so it can be merged once that's been fixed!

@jazanne
jazanne requested a review from cspath1 July 15, 2026 16:06
@cspath1
cspath1 merged commit d2b674b into launchdarkly:main Jul 15, 2026
5 checks passed
@jazanne jazanne mentioned this pull request Jul 28, 2026
apucacao added a commit that referenced this pull request Jul 28, 2026
## Summary

Prepares the 2.16.0 release by hand. This is the same approach taken for
2.14.0 in #563: the release workflow can publish artifacts but cannot
complete a release, so the version bump lands as a normal PR and the
tag, GitHub release, and downstream action update are done manually
afterward.

Related to #607 — the fix being asked for there is #604. That issue
stays open until the release and the downstream action update are
actually out.

## Why by hand

`scripts/release/prepare-release.sh` commits the version bump and
changelog entry, then `push-to-origin.sh` pushes that commit straight to
`main`. Rulesets reject it:

```
remote: error: GH013: Repository rule violations found for refs/heads/main
remote: - Changes must be made through a pull request.
 ! [remote rejected] HEAD -> main
```

This has now failed the same way three times: August 2025 (worked around
manually in #563), January 2026 (#593#595, which disabled the
GHA/Bitbucket/CircleCI publish targets to get a Docker-only release
out), and again today. The plan stated in #563 was to move to Release
Please so that releasing never pushes to `main`. That hasn't happened
yet, so this PR follows the manual path again.

## What changed

| File | Change |
| --- | --- |
| `internal/version/version.go` | `2.14.0` → `2.16.0` |
| `CHANGELOG.md` | 2.16.0 entry, plus a note that 2.15.0 was never
released |
| `build/metadata/github-actions/Dockerfile` | image tag → `2.16.0` |
| `build/metadata/github-actions/README.md` |
`find-code-references@v2.16.0` |

## Behavior notes

- **Numbering skips 2.15.0.** January's run pushed
`ld-find-code-refs:2.15.0` and `ld-find-code-refs-github-action:2.15.0`
to Docker Hub before failing, so those tags are already taken. Releasing
as 2.16.0 keeps published images immutable.
- **Docker images for 2.16.0 are already published.** Today's run got as
far as `publish` before failing, so `2.16.0` and `latest` are on Docker
Hub, built from `d2b674b` with the version constant patched to 2.16.0.
- **`brew install ld-find-code-refs` is broken right now.** That same
run updated the homebrew tap formula to 2.16.0, but its download URLs
point at release assets that don't exist yet. Creating the GitHub
release fixes it; the shas need regenerating because the assets will
come from a local build rather than the CI build.
- **Bitbucket and CircleCI metadata deliberately untouched.** Those
targets stopped being published in January, so bumping them would name a
pipe version and orb version that were never cut.

## Testing

`go build ./...` and `go test ./aliases/...` pass. Nothing here is
executable code beyond the version constant.

## Provenance

Rebuilt as two narrative commits on `release-2.16.0-clean`; the original
branch is
[`release-2.16.0`](https://github.com/launchdarkly/ld-find-code-refs/tree/release-2.16.0).
Tree hashes verified identical.
apucacao added a commit to launchdarkly/find-code-references that referenced this pull request Jul 28, 2026
## Summary

Points the action at `ld-find-code-refs` 2.16.0, which was released
today:
https://github.com/launchdarkly/ld-find-code-refs/releases/tag/v2.16.0

The headline fix is out-of-memory failures when generating filepattern
aliases on large repositories
([ld-find-code-refs#604](launchdarkly/ld-find-code-refs#604)).
On a repo with ~80MB of matched source and ~160 flags, the scan was
OOM-killed before producing any output. Users pinned to `@v2` or
`@v2.14.0` are still hitting that until this merges.

Requested in
[ld-find-code-refs#607](launchdarkly/ld-find-code-refs#607).

## What changed

| File | Change |
| --- | --- |
| `Dockerfile` | `FROM
launchdarkly/ld-find-code-refs-github-action:2.14.0` → `:2.16.0` |
| `README.md` | pinned version in both workflow examples → `@v2.16.0` |

Both files were copied verbatim from `build/metadata/github-actions/` in
`launchdarkly/ld-find-code-refs`, which is the source of truth for them.
`action.yml` was already identical and is untouched.

## Why this is a manual PR

`scripts/release/targets/gha.sh` normally does this automatically during
the upstream release: it copies the metadata files here, commits, tags,
force-moves `v2`, and creates the release. That target (`publish_gha`)
has been commented out since
[ld-find-code-refs#593](launchdarkly/ld-find-code-refs#593)
in January 2026, so it's being done by hand.

Direct pushes to `main` are rejected by rulesets, which is also why the
upstream release workflow can't complete on its own — hence the PR
rather than a bot push.

## After merge

1. Tag `v2.16.0` at the merge commit.
2. Force-move the `v2` tag so `@v2` users get the fix.
3. Create the `v2.16.0` release.

## Note on version numbering

Jumps 2.14.0 → 2.16.0. 2.15.0 was never released — an incomplete release
run in January 2026 published its Docker images and then failed, leaving
no tag or release behind, so that number was already burned.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants