Launching a campaign
On the Remediation page:- Click New campaign in the toolbar.
- Name it (e.g. Pin actions to SHA — Q3).
- Select the repositories to include.
- Click Open PRs in N repos.
Admin only. Launching a campaign — and remediating repos within one — is
restricted to organization admins, since it opens pull requests across the
org’s repositories. Any member can view campaign trackers.
What gets fixed
Campaigns remediate workflow-YAML findings that have an auto-fix — the same fixer registry behind the per-finding Fix button (pinning actions to SHAs, adding least-privilegepermissions, adding timeouts/concurrency,
removing debug logging, and so on). For each repository, the campaign:
- fetches and scans the repo’s CI workflow files in memory (nothing is cloned),
- honors your rule settings — disabled rules are never “fixed”,
- opens one pull request per remediable workflow file — every fixable finding in that file is applied in a single commit, so a workflow with five issues gets one PR to review, not five — or reuses the existing Pipefort fix PR if one is already open,
- records the outcome.
Per-repo status
The campaign itself is running until every repo reaches a terminal state,
then completed.
The queue opens on your most recent campaign; the picker in the toolbar
switches between them, and the tabs filter by outcome — all, with PRs,
nothing to fix, failed — each showing its own count. CSV downloads
the whole table: one row per repository with its status, PR count, fixes
applied, PR URLs, and any error.
The fix tracker
Above the campaign queue, Remediation tracks every fix pull request Pipefort has opened — from a campaign or from a single finding — in three states:
Merged but the finding came back is the row worth watching. Somebody
believed the problem was fixed and a later scan disagreed, which is a different
and more expensive failure than a fix nobody merged.
The header reports how many need a person, how many landed, and the median
time from opening to merge.
Why a fix is stuck
What is happening inside an open pull request does not arrive on any webhook Pipefort receives: mergeability is computed by GitHub only when asked, and check conclusions and requested reviewers belong to event types the App does not subscribe to. So it is polled, by the dailyGET /api/cron/refresh-fix-prs, and each row shows what GitHub said when it
was last asked.
When several are true at once the row shows the most blocking one, because
the question it answers is “what is the next thing somebody has to do” — a pull
request with a conflict and a red check is a conflict, since resolving it
re-runs the checks.
A poll is a photograph. Every row is only true as of the moment it was taken,
which is why the footnote states how recently. If the cron has never run, rows
say “opened, no outcome yet” and the footnote says nothing has looked
inside them — that is deliberately not the same as a clean bill of health.
A merge is not a resolution. The finding stays open and stays in the posture
counts until a later scan stops seeing it. A fix made by hand, outside Pipefort
entirely, closes a finding the same way.
What the campaign queue cannot tell you
The queue below the tracker is about the moment the campaign ran — what it managed to open, and what it could not. What became of each PR afterwards is the tracker’s job, not the queue’s.Retrying
Launching a campaign never opens the same pull request twice: each repository is claimed before its fixes run, so a double-click, a page refresh mid-run, or a second admin working in another tab won’t duplicate the work. Repositories that failed can be retried — relaunching remediation for them picks the campaign back up and returns it to running. Repositories that already finished are left alone.GitLab
Campaigns are provider-neutral: for GitLab-hosted repositories the campaign opens merge requests through the same flow.API
Campaigns are driven by three endpoints — see the API reference:POST /api/campaigns— create a campaign over selected repos (admin only).POST /api/campaigns/{id}/repos/{repo_id}/remediate— remediate one repo (admin only; the SPA loops this with bounded concurrency).GET /api/campaigns/{id}— the tracker: campaign, per-repo statuses, and the rollup.
remediation_campaigns, campaign_repos), scoped to your organizations.