Is automated flag removal safe to let into my repo?
Last updated:
The Action runs inside your own CI, so the only credential holding write access to your repository is the GITHUB_TOKEN that workflow already has. The Featureflip token you supply reads removal candidates and nothing else, and a Viewer token scoped to one project is enough. Every change arrives as a pull request you review, and dry-run mode prints each diff without contacting GitHub at all.
Something is about to open pull requests against your source. Start with the credential.
Which credential can write to your repo
The Featureflip cleanup Action is a step in your own workflow. It runs on your runner, against a checkout you made, and the thing that writes to your repository is the GITHUB_TOKEN that workflow already carries:
permissions: contents: write # push the removal branch pull-requests: write # open the PRTwo scopes. That is the whole ask. No app gets installed on the repository, and the parsing and rewriting both happen inside the container on your runner, so your source never leaves it.
The Featureflip token you pass in is the other credential, and it points the other way. In remove mode the Action only reads from the API, so a Viewer token restricted to one project covers it. That token cannot archive, toggle or delete a flag. Retiring the flag once its removal lands stays a decision you make, and the separate workflow that automates it carries its own write-scoped secret.
Nothing merges itself
Each flag gets one pull request. Dead flags open ready for review, stale flags open as drafts, and both then wait for whatever reviewers and status checks your repository already requires before anything can land on your default branch.
There is a cap on how many pull requests one run may open. Set it low the first time:
with: max-prs: 3If something about a run is wrong, that bounds how many pull requests are wrong before a person sees one. Nothing is lost by capping it, because the next run picks up the flags this one did not reach.
What a run refuses to touch
The rewriter carries a fixed list of shapes it will not fold, and it says so when it hits one. Hit a mock stub holding a flag read and the flag stops, non-zero, file named. Keys that are not string literals at the read site produce no diff. Your own wrapper function around the SDK is left alone, which is far and away the most common reason a run reports no changes for a flag you can grep for in forty files.
None of those produce a partial rewrite. Each is printed with a label, and the reasoning behind every entry on that list is the specification for the whole tool.
Watching a whole run before it touches anything
Set dry-run: true and the Action computes and prints the diff for every candidate while never contacting GitHub, not even to check whether a pull request already exists for a flag:
with: dry-run: true flags: checkout-v2Every refusal a real run can produce is reachable in a dry run and is labeled identically, so the preview cannot approve a flag that the next real run turns down. Adding flags narrows the whole thing to one key.
Those are the same rules a real run applies to your real source, with nothing written down anywhere, so you can read a whole run through before deciding whether this workflow gets the two scopes above.
Related questions
Why didn't the cleanup Action remove my flag?
A cleanup run that reports no changes for a flag your code reads everywhere is almost always a wrapper function. The other causes, and how to tell them apart.
What if I archive a flag still used in my code?
An archived flag leaves the SDK configuration, so any remaining call site falls back to the default you passed. Remove the code first, then archive.
Still stuck?
The docs cover every SDK, and the free Solo plan is enough to reproduce most of these locally.