Note in AGENTS.md and the PR review workflow that
content/reference/api/ai-governance/api.yaml is a verbatim copy of the
upstream OpenAPI spec, vendored from the private docker/governor-services
repo via hack/sync-governance-api.sh, and should not be hand-edited.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
<!--Delete sections as needed -->
## Description
Fix stale action not closing PRs due to missing `actions: write`
permission
The stale action uses GitHub Actions cache to persist state between
runs. Without `actions: write`, it can't delete its `_state` cache entry
(fails with 403), so the old state accumulates and PRs in that cached
state are permanently skipped with `processed during the previous run`,
meaning they never get evaluated for closing.
Confirmed via Actions logs: PR #23598 was marked stale on April 24 but
has never been evaluated for closing because it appears in the stuck
cache state every run.
## Related issues or tickets
<!-- Related issues, pull requests, or Jira tickets -->
## Reviews
<!-- Notes for reviewers here -->
<!-- List applicable reviews (optionally @tag reviewers) -->
- [ ] Technical review
- [ ] Editorial review
- [ ] Product review
Signed-off-by: Craig Osterhout <craig.osterhout@docker.com>
## Summary
An audit of docker-agent review comments across recent merged PRs
surfaced two
recurring false positives, both traced to their source:
- The bot's prompt (`.github/workflows/pr-review.yml`) instructed it to
flag
lines over 80 characters, but no such rule exists — markdownlint MD013
is
disabled and STYLE.md never mentions it. The bot itself conceded this
mid-review on a past PR. Removed the instruction.
- STYLE.md's word list banned "enable" yet used it in a ✅ example, so
the bot
flagged every "enable"/"disable" as a violation. Added a note clarifying
that
"turn on/off" is for UI toggles while "enable/disable" is fine in
general
prose.
## Learnings
- The docker-agent PR reviewer is driven by the `additional-prompt`
block in
`.github/workflows/pr-review.yml` (via `docker/cagent-action`), plus
`STYLE.md` and `COMPONENTS.md` loaded as prompt files. That prompt — not
just
the style guides — is the source of truth for what the bot flags, so
review
noise can be tuned there directly.
Generated by Claude Code
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Problem
The labeler workflow has been silently skipping labels on some PRs. The
runs show up as `cancelled` rather than `success`.
Root cause is the concurrency config:
```yaml
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
```
The workflow triggers on `pull_request_target`, and for that event
`github.ref` resolves to the **base branch** (`refs/heads/main`), not
the PR head ref. So every labeler run across **all** open PRs lands in
the same concurrency group (`labeler-refs/heads/main`), and
`cancel-in-progress: true` kills whichever run is in flight as soon as
another PR triggers the workflow.
When several PRs are created or updated within seconds of each other,
the earlier runs get cancelled before they finish labeling. Example from
recent runs:
- `sbx-policy-recipes` (cancelled) ← cancelled by `remove-api-header`
(success) seconds later
- `sbx-linux-keychain` (cancelled) ← cancelled by `storage-drivers`
(success) seconds later
## Fix
Key the concurrency group on the PR number instead, falling back to
`github.ref` for non-PR contexts, so each PR gets its own group and runs
no longer cancel each other.
```yaml
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
```
> [!NOTE]
> A separate, rarer class of labeler failures (genuine `failure` status)
was caused by transient GitHub infrastructure errors downloading the
pinned action tarball at the "Set up job" step. Those are not addressed
here as they only need a re-run.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The PR-review bot's prompt instructed it to flag lines over 80 characters,
but no such rule exists in the repo (markdownlint MD013 is disabled and
STYLE.md never mentions it). Remove that instruction from pr-review.yml.
Also clarify the STYLE.md word list so "turn on/off" applies to UI toggles
while "enable/disable" stays acceptable in general prose, matching STYLE.md's
own example. This stops the bot from flagging every "enable" as a violation.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v1.5.2's review-pr/action.yml has a YAML parse error at line 822 that
breaks the PR review workflow. Tracking upstream at
docker/cagent-action#205.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Switch trigger from workflow_dispatch back to pull_request_target.
The workflow does not check out PR code so pull_request_target is safe.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
<!--Delete sections as needed -->
## Description
Link to contribute guide no longer exists.
Updated message to remove link or point to relevant link.
## Related issues or tickets
<!-- Related issues, pull requests, or Jira tickets -->
## Reviews
<!-- Notes for reviewers here -->
<!-- List applicable reviews (optionally @tag reviewers) -->
- [ ] Editorial review
Signed-off-by: Craig Osterhout <craig.osterhout@docker.com>
<!--Delete sections as needed -->
## Description
This PR adds a GitHub Actions workflow to automatically mark and close
stale issues and PRs, helping maintainers focus on active items. The old
app/bot stopped working around mid 2025 and was disabled. This
reimplements it using a GitHub Action with additional slash command
functionality.
### Timeframes
- **Mark as stale**: After **180 days** (6 months) of inactivity
- **Close stale issues**: After **14 additional days** of no activity
- **Close stale PRs**: After **30 additional days** of no activity
### Exempt Labels
Issues and PRs with any of these labels will never be marked as stale:
- `kind/help-wanted`
- `status/need-more-info`
- `status/needs-analysis`
- `lifecycle/frozen`
### How to Keep Issues/PRs Active
To prevent an issue or PR from being marked as stale or closed:
**Anyone can:**
1. **Add a comment** - any comment resets the inactivity timer
2. **Use `/lifecycle active`** - removes the stale label via slash
command
**Maintainers can also:**
3. **Use `/lifecycle frozen`** - prevents the issue/PR from ever being
marked stale
4. **Add exempt labels** - manually apply one of the labels listed above
5. **Make any update** - editing the description, adding labels, or any
activity resets the timer
### Slash Commands
The workflow supports these lifecycle commands (comment them on any
issue/PR):
| Command | Access | Description |
|---------|--------|-------------|
| `/lifecycle active` | Anyone | Removes the stale label |
| `/lifecycle frozen` | Write access required | Prevents stale marking |
| `/lifecycle stale` | Write access required | Manually marks as stale |
| `/remove-lifecycle frozen` | Write access required | Removes frozen
label |
| `/remove-lifecycle stale` | Anyone | Removes stale label |
Commands respond with a 👍 reaction when successful, 👎 when permission is
denied.
### Messages
When marked as stale, issues and PRs receive a friendly comment
explaining:
- The situation and timeline for closure (14-30 days)
- How to remove the stale label using `/lifecycle active`
- How maintainers can freeze with `/lifecycle frozen`
### Debug Mode
The workflow is currently set to **debug mode** for both components:
**Stale action** (`debug-only: true`):
- ✅ Runs and logs what actions it would take
- ❌ No actual changes will be made (no labels, comments, or closures)
**Lifecycle commands** (`DEBUG_ONLY: 'true'`):
- ✅ Logs what would happen when slash commands are used
- ❌ No labels added, removed, or permission checks enforced
## Related issues
- #19050
---------
Signed-off-by: Craig Osterhout <craig.osterhout@docker.com>
The CloudFront Lambda rewrote `/` with `Accept: text/markdown` to an
invalid `.md` URI, causing a 502 LambdaValidationError. Homepage has no
flattened markdown equivalent, so route to `/llms.txt` — the
agent-oriented markdown index of the site. Same handling for
`/index.html`.
Also set `Content-Type: text/markdown` on `llms.txt` at upload time, so
content negotiation responses and direct requests both advertise the
correct media type.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
## Description
The `release-notes-pr-trigger` workflow was interpolating PR context
values
(`html_url`, `title`, `user.login`) directly into a shell heredoc. A
specially crafted PR title or author name could break out of the JSON
string
and execute arbitrary commands.
This change moves the GitHub context values into environment variables
and
uses `jq` to safely construct the JSON artifact, eliminating the
injection
vector.
## Related issues or tickets
None
## Reviews
- [x] Technical review
Signed-off-by: Lorena Rangel <lorena.rangel@docker.com>
Rewrites the scanner instruction to focus on substantive documentation
problems rather than mechanical style violations. Key changes:
- Adds a 4-question self-check gate before any issue is filed
- Explicitly excludes broken links, single time-relative words, feature
gates (Limited Access, Contact sales), and vague verification tasks
- Replaces "max 3 per run" with "file zero if nothing substantive found"
- Elevates cross-document contradiction detection as the primary focus
- Adds "Why this matters" section to issue template to force impact reasoning
- Adds --repo docker/docs to gh commands for correctness outside repo root
Based on analysis of all agent/generated issues to date: borderline
issues like #24266, #24245, #24310 were all single Vale-catchable words;
bad issues like #24617, #24618, #24619 were feature-gate misidentification
and vague verification tasks.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
## Description
The Slack notification workflow for Desktop release notes PRs fails when
the PR is opened from a fork because GitHub doesn't expose repository
secrets to `pull_request` events from forks.
This PR splits the workflow into two:
1. **Release Notes PR Trigger** — runs on `pull_request`, saves PR
details (URL, title, author) as an artifact. No secrets needed.
2. **Notify Slack on Desktop Release Notes PR** — runs on `workflow_run`
after the trigger completes, downloads the artifact, and sends the
Slack notification. Has access to secrets since `workflow_run` runs in
the context of the base repository.
## Related issues or tickets
Fixes the `SlackError: Missing input! A token must be provided` error
in the notify-release-notes-pr workflow.
## Reviews
- [x] Technical review
Signed-off-by: Lorena Rangel <lorena.rangel@docker.com>
<!--Delete sections as needed -->
## Description
Adds a GitHub Actions workflow that posts a Slack notification when a
pull request is opened that modifies the Desktop release notes page
(content/manuals/desktop/release-notes.md).
The workflow uses slackapi/slack-github-action v3.0.1 and sends a
message with a link to the PR and the author's GitHub profile to the
configured Slack channel.
Will need to add the secrets.
## Related issues or tickets
n/a
## Reviews
<!-- Notes for reviewers here -->
<!-- List applicable reviews (optionally @tag reviewers) -->
- [x] Technical review
- [ ] Editorial review
- [ ] Product review
Signed-off-by: Lorena Rangel <lorena.rangel@docker.com>
pr-review: drop pull_request_target (auto-review on open/ready_for_review).
Manual /review via issue_comment is preserved and unaffected.
labeler: replace pull_request_target with workflow_dispatch to disable
automatic fork-PR labeling. Can be re-enabled by reverting this change.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All mutable action tags replaced with verified commit SHAs to prevent
supply-chain attacks via tag mutation. package.json ^ ranges replaced
with exact versions from package-lock.json.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>