Epic: GitHub Actions code references integration
From #5066.
User Experience Proposal
When viewing stale feature flags in the Flagsmith UI, display feature flag references found in repositories from the team's GitHub organization.
Mockups: https://github.com/Flagsmith/flagsmith/issues/5728
This is intended to prompt developers to clean up stale feature flags by making it easier to coordinate work — and maybe positively annoying.
GitHub Actions
By leveraging GitHub Actions, we can build a CI product that is easy to plug in and comes with a great architecture fit.
- GHA allows for code scans triggered by each team's git-push activity, also expanding visibility to PRs and releases.
- Favoring privacy, our code runs in CI runners chosen by each team — could be GitHub runners, or their own. We do not have access to anyone's code.
- It offloads computer work to each team's CI cost with GHA.
The above diagram is an architecture overview of how customers, such as github.com/acmeinc, can plug in a GitHub action from github.com/Flagsmith/ci-tools. A CI workflow snippet in GitHub Actions language would resemble this untested snippet:
name: find-flagsmith-code-references
on:
pull_request:
push:
branches: [main]
schedule:
- cron: '0 8 * * *' # Every day at 8 am UTC
jobs:
fetch-stale-feature-flags:
if: github.event_name == 'schedule'
uses: flagsmith/ci-tools/.github/workflows/[email protected]
secrets:
flagsmith_server_key: ${{ secrets.FLAGSMITH_SERVER_KEY }}
report-code-references-from-stale-feature-flags:
needs: [fetch-stale-feature-flags]
if: ${{ needs.fetch-stale-feature-flags.outputs.stale_features }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker://ghcr.io/flagsmith/flagsmith-find-code-references:0.0.1
id: find_stale_flag_code_references
with:
features: ${{ needs.fetch-stale-feature-flags.outputs.stale_features }}
flagsmith_server_key: ${{ secrets.FLAGSMITH_SERVER_KEY }}
- uses: flagsmith/ci-tools/.github/actions/[email protected]
with:
references_json: ${{ steps.find_stale_flag_code_references.outputs.references_json }}
report-code-references-from-diff:
if: contains(fromJSON('["push", "pull_request"]'), github.event_name)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker://ghcr.io/flagsmith/flagsmith-find-code-references:0.0.1
id: find_diff_flag_code_references
with:
from_diff_since: ${{ github.event.pull_request.head.sha }}
flagsmith_server_key: ${{ secrets.FLAGSMITH_SERVER_KEY }}
- uses: flagsmith/ci-tools/.github/actions/[email protected]
with:
references_json: ${{ steps.find_diff_flag_code_references.outputs.references_json }}
Proof of Concept
The PoC is an ad-hoc, non-reusable workflow in the Flagsmith repository that sends code references to the Flagsmith API. This enables the team to evaluate the GitHub integration using internal data.
Scope
The PoC workflow triggers on a daily schedule against the main branch. This constraint ensures code references reflect production code only.
Implementation
The PoC consists of:
-
CI workflow (
.github/workflows/poc-github-code-references.yml): Scans the codebase for feature flag references and uploads them to the Flagsmith API. - Backend endpoints: Receive and persist code references, and serve them for display.
- Frontend components: Display code reference counts in the feature list and detailed references in the feature modal.
Related Work
- #5727: PoC Release (Epic)
- #5728: Frontend work for GitHub code references PoC (mockups)
- #5731: CI workflow to find feature flag references
- #5854: Find feature flag references in the code (CI)
- #5928: Submit feature flag code references (API)
- #5931: Retrieve feature code references (API)
- #5939: Frontend GitHub code references (UI)
-
As far as I understand our product, instead of inventing arbitrary logic for detecting stale flags, we should look for features tagged as Stale, and improve the tagging logic instead. This invalidates #5703 and, in part, #5701. @matthewelwell feel free to intervene here.
-
I'd rather we think on the UX more, and provide a more meaningful and ergonomic set of actions. For instance, I don't understand yet why we need a dedicated reusable workflow to perform one API call. Why can't we bundle it with the action itself, and cache the results? It would shave off a whole job from your example workflow code.
we should look for features tagged as Stale, and improve the tagging logic instead.
I just came across the stale tag type in the code, thanks for pointing it out! I was under the impression the definition of stale was time-based since the flag's last update. Let's use #5703 to discuss and reshape or close the issue.
I don't understand yet why we need a dedicated reusable workflow to perform one API call.
One reason is privacy: actions can have access to the code (if they come after actions/checkout), while reusable workflows don't need to. With that in mind, a granular trio (1. retrieve flags, 2. scan code, and 3. push references) would allow us to prevent privacy concerns. However, it's important to note that we don't need to go that route yet for a POC.
Another reason is CI flexibility. If we ship reusable workflows along with an action, we can make it easier for customers to set up Flagsmith CI, as they can just use one workflow from github.com/flagsmith/ci for both releases, pull-requests, or any other event, rather than having to set up a new workflow and rely on instructions on how to use the action along with it.
And then another reason is portability. Having granular steps makes it easier for us to develop and maintain the same functionality across multiple CI vendors besides GHA in the future.
The architecture is meant to reduce the integration steps, in despite of giving us a bit more work. Then again: during this POC phase, we'll likely skip a lot of that.
Let me know if that makes sense.
Interesting discussion here. Let's visit that after the PoC (#5727).