diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 45edbed0b7..c886a192d0 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -114,6 +114,7 @@ export default defineConfig({ { label: 'Custom Safe Outputs', link: '/guides/custom-safe-outputs/' }, { label: 'Threat Detection', link: '/guides/threat-detection/' }, { label: 'Web Search', link: '/guides/web-search/' }, + { label: 'Ephemerals', link: '/guides/ephemerals/' }, ], }, { diff --git a/docs/src/content/docs/guides/ephemerals.md b/docs/src/content/docs/guides/ephemerals.md new file mode 100644 index 0000000000..8c809fccdf --- /dev/null +++ b/docs/src/content/docs/guides/ephemerals.md @@ -0,0 +1,399 @@ +--- +title: Ephemerals +description: Features for automatically expiring workflow resources and reducing noise in your repositories +sidebar: + order: 9 +--- + +GitHub Agentic Workflows includes several features designed to automatically expire resources and reduce noise in your repositories. These "ephemeral" features help keep your repository clean by automatically cleaning up temporary issues, discussions, pull requests, and workflow runs after they've served their purpose. + +## Why Use Ephemerals? + +**Cost Control**: Scheduled workflows can accumulate costs over time. Setting expiration dates ensures they stop automatically after a deadline. + +**Reduce Clutter**: AI-generated issues and discussions can accumulate quickly. Auto-expiration removes obsolete content, keeping your repository focused on active work. + +**Status Updates**: When workflows post status updates repeatedly, hiding older comments prevents timeline clutter while preserving the latest information. + +**Clean Automation**: Prevent automated content from overwhelming your main repository by using separate repositories and controlling cross-references. + +## Expiration Features + +### Workflow Stop-After + +Automatically disable workflow triggering after a deadline to control costs and prevent indefinite execution. + +```yaml wrap +on: + schedule: + - cron: "0 9 * * 1" + stop-after: "+25h" # 25 hours from compilation time +``` + +**Accepted formats**: +- **Absolute dates**: `YYYY-MM-DD`, `MM/DD/YYYY`, `DD/MM/YYYY`, `January 2 2006`, `1st June 2025`, ISO 8601 +- **Relative deltas**: `+7d`, `+25h`, `+1d12h30m` (calculated from compilation time) + +The minimum granularity is hours - minute-only units (e.g., `+30m`) are not allowed. Recompiling the workflow resets the stop time. + +**Key behaviors**: +- The workflow is disabled at the specified deadline, preventing new runs +- Existing runs continue to completion +- The stop time is preserved during recompilation unless `--refresh-stop-time` flag is used +- Use `gh aw compile --refresh-stop-time` to regenerate the stop time based on current time + +**Use cases**: +- Trial workflows that should run for a limited period +- Experimental features with automatic sunset dates +- Campaign workflows with defined end dates +- Cost-controlled scheduled workflows + +See [Triggers Reference](/gh-aw/reference/triggers/#stop-after-configuration-stop-after) for complete documentation. + +### Safe Output Expiration + +Auto-close issues, discussions, and pull requests after a specified time period. This generates a maintenance workflow that runs automatically at appropriate intervals. + +#### Issue Expiration + +```yaml wrap +safe-outputs: + create-issue: + expires: 7 # Auto-close after 7 days + labels: [automation, agentic] +``` + +#### Discussion Expiration + +```yaml wrap +safe-outputs: + create-discussion: + expires: 3 # Auto-close after 3 days as "OUTDATED" + category: "general" +``` + +#### Pull Request Expiration + +```yaml wrap +safe-outputs: + create-pull-request: + expires: 14 # Auto-close after 14 days (same-repo only) + draft: true +``` + +**Supported formats**: +- **Integer**: Number of days (e.g., `7` = 7 days) +- **Relative time**: `2h`, `7d`, `2w`, `1m`, `1y` + +Hours less than 24 are treated as 1 day minimum for expiration calculation. + +**Maintenance workflow frequency**: The generated `agentics-maintenance.yml` workflow runs at the minimum required frequency based on the shortest expiration time across all workflows: + +| Shortest Expiration | Maintenance Frequency | +|---------------------|----------------------| +| 1 day or less | Every 2 hours | +| 2 days | Every 6 hours | +| 3-4 days | Every 12 hours | +| 5+ days | Daily | + +**Expiration markers**: The system adds an XML comment to the body of created items: +```html + +``` + +The maintenance workflow searches for items with expired timestamps and automatically closes them with appropriate comments and resolution reasons. + +See [Safe Outputs Reference](/gh-aw/reference/safe-outputs/) for complete documentation. + +### Close Older Discussions + +Automatically close older discussions matching the same title prefix or labels when creating new ones. This keeps your discussions focused on the latest information. + +```yaml wrap +safe-outputs: + create-discussion: + title-prefix: "[weekly-report]" + labels: [automation, weekly] + close-older-discussions: true # Close previous reports +``` + +**How it works**: +- When a new discussion is created successfully, the system searches for older discussions +- Matches are identified by title prefix OR any of the specified labels +- Up to 10 older discussions are closed as "OUTDATED" +- Each closed discussion receives a comment linking to the new discussion +- Only runs if the new discussion creation succeeds + +**Requirements**: +- Must set `title-prefix` or `labels` (or both) to identify matching discussions +- Requires appropriate permissions on the target repository + +**Use cases**: +- Weekly status reports where only the latest matters +- Recurring analysis workflows that supersede previous results +- Scheduled summaries that replace older versions + +## Noise Reduction Features + +### Hide Older Comments + +Minimize previous comments from the same workflow before posting new ones. Useful for status update workflows where only the latest information matters. + +```yaml wrap +safe-outputs: + add-comment: + hide-older-comments: true + allowed-reasons: [outdated] # Optional: restrict hiding reasons +``` + +**How it works**: +- Before posting a new comment, searches for previous comments from the same workflow +- Identifies comments by `GITHUB_WORKFLOW` name +- Hides (minimizes) matching comments in the GitHub UI +- Posts the new comment +- Only hides comments; does not delete them + +**Allowed reasons**: +- `spam` - Mark as spam +- `abuse` - Mark as abusive +- `off_topic` - Mark as off-topic +- `outdated` - Mark as outdated (default) +- `resolved` - Mark as resolved + +Configure `allowed-reasons` to restrict which reasons can be used. If omitted, only `outdated` is allowed by default. + +**Use cases**: +- Workflows posting status updates repeatedly +- Build status notifications where only latest result matters +- Health check workflows reporting periodic results +- Progress tracking workflows with frequent updates + +See [Safe Outputs Reference](/gh-aw/reference/safe-outputs/#hide-older-comments) for complete documentation. + +### SideRepoOps Pattern + +Run agentic workflows from a separate "side" repository that targets your main codebase. This isolates AI-generated issues, comments, and workflow runs from your main repository, keeping automation infrastructure separate from production code. + +```yaml wrap +safe-outputs: + github-token: ${{ secrets.MAIN_REPO_PAT }} + create-issue: + target-repo: "my-org/main-repo" + title-prefix: "[automation] " + labels: [automation, ai-generated] +``` + +**Key benefits**: +- **Zero friction** - No changes needed to main repository +- **Clean separation** - AI-generated issues stay separate from organic development +- **Private workflows** - Store sensitive automation logic in private repository +- **Safe experimentation** - Test workflows without affecting production +- **Centralized automation** - Manage workflows for multiple repositories + +**Architecture**: +```text +┌─────────────────┐ ┌──────────────────┐ +│ Side Repo │ │ Main Repo │ +│ (workflows) │ ────────>│ (target code) │ +│ │ Uses │ │ +│ - automation/ │ PAT │ - src/ │ +│ - .github/ │ │ - tests/ │ +│ workflows/ │ │ - docs/ │ +└─────────────────┘ └──────────────────┘ +``` + +The workflows run in GitHub Actions on the side repository but perform operations (create issues, PRs, comments) on the main repository using cross-repository authentication. + +See [SideRepoOps Guide](/gh-aw/guides/siderepoops/) for complete setup and usage documentation. + +### Allowed GitHub References + +Control which GitHub repository references (`#123`, `owner/repo#456`) are allowed in workflow output. When configured, references to unlisted repositories are escaped with backticks to prevent GitHub from creating timeline items. + +```yaml wrap +safe-outputs: + allowed-github-references: [] # Escape all references + create-issue: + target-repo: "my-org/main-repo" +``` + +**Configuration options**: +- `[]` — Escape all references (prevents all timeline items) +- `["repo"]` — Allow only the target repository's references +- `["repo", "owner/other-repo"]` — Allow specific repositories +- Not specified (default) — All references allowed + +**How it works**: References like `#123` become `` `#123` `` and `other/repo#456` becomes `` `other/repo#456` ``, preventing timeline clutter while preserving the information. + +**Use cases**: +- **SideRepoOps**: Prevent automation from cluttering main repository timeline +- **Cross-repository operations**: Avoid unwanted cross-references +- **Clean automation**: Maintain readable issue/PR timelines +- **Reporting workflows**: Share information without creating link noise + +**Example with SideRepoOps**: +```yaml wrap +safe-outputs: + github-token: ${{ secrets.MAIN_REPO_PAT }} + allowed-github-references: [] # Escape all references + create-issue: + target-repo: "my-org/main-repo" + title-prefix: "[automation] " +``` + +This prevents the side repository's automation from creating "mentioned in..." entries in your main repository's issues and pull requests. + +See [Safe Outputs Reference](/gh-aw/reference/safe-outputs/#security-and-sanitization) for complete documentation. + +### Use Discussions Instead of Issues + +For ephemeral content, use GitHub discussions instead of issues. Discussions are better suited for temporary content, questions, and updates that don't require long-term tracking. + +```yaml wrap +safe-outputs: + create-discussion: + category: "general" + expires: 7 # Auto-close after 7 days + close-older-discussions: true +``` + +**Why discussions for ephemeral content?** + +| Feature | Issues | Discussions | +|---------|--------|-------------| +| **Purpose** | Long-term tracking | Conversations & updates | +| **Searchability** | High priority in search | Lower search weight | +| **Project boards** | Native integration | Limited integration | +| **Auto-close** | Supported with maintenance workflow | Supported with maintenance workflow | +| **Timeline noise** | Can clutter project tracking | Separate from development work | + +**Use cases for ephemeral discussions**: +- Weekly status reports +- Periodic analysis results +- Temporary announcements +- Q&A that expires +- Time-bound experiments +- Community updates + +**Combining features**: +```yaml wrap +safe-outputs: + create-discussion: + title-prefix: "[weekly-status]" + category: "Status Updates" + labels: [automation, weekly] + expires: 14 # Close after 2 weeks + close-older-discussions: true # Replace previous reports +``` + +This configuration ensures: +1. Only the latest weekly status discussion is open +2. Previous reports are closed when new ones are created +3. All discussions auto-close after 14 days +4. The "Status Updates" category stays clean and focused + +## Best Practices + +### Combining Expiration Features + +Use multiple expiration features together for comprehensive cleanup: + +```yaml wrap +on: + schedule: + - cron: "0 9 * * 1" + stop-after: "+30d" # Stop workflow after 30 days + +safe-outputs: + create-discussion: + title-prefix: "[experiment]" + expires: 7 # Close discussions after 7 days + close-older-discussions: true # Close older when creating new + add-comment: + hide-older-comments: true # Minimize old status updates +``` + +This ensures the workflow stops after 30 days, created discussions expire after 7 days, and older discussions/comments are cleaned up automatically. + +### Labeling Ephemeral Content + +Use consistent labels to identify and track ephemeral content: + +```yaml wrap +safe-outputs: + create-issue: + expires: 7 + labels: [ephemeral, automation, expires-7d] +``` + +This makes it easy to: +- Identify ephemeral content at a glance +- Filter by expiration timeframe +- Audit what content will expire soon +- Track automation-generated content + +### SideRepoOps with Reference Escaping + +When using SideRepoOps, always configure `allowed-github-references` to prevent timeline noise: + +```yaml wrap +safe-outputs: + github-token: ${{ secrets.MAIN_REPO_PAT }} + allowed-github-references: [] # Escape all references + create-issue: + target-repo: "my-org/main-repo" + expires: 7 # Auto-close after 7 days + labels: [automation, ephemeral] +``` + +This combination ensures: +- Issues are created in the main repo but tracked separately +- No cross-references clutter the main repo timeline +- Content auto-expires after 7 days +- Clear labeling identifies automated content + +### Status Update Workflows + +For workflows that post repeated status updates, use comment hiding: + +```yaml wrap +safe-outputs: + add-comment: + hide-older-comments: true + allowed-reasons: [outdated, resolved] +``` + +This ensures: +- Only the latest status is prominently visible +- Historical status updates are preserved but minimized +- Timeline stays clean and focused +- Multiple status reasons available (outdated, resolved) + +### Maintenance Workflow Monitoring + +The auto-generated `agentics-maintenance.yml` workflow handles expiration. Monitor its runs to ensure proper cleanup: + +```bash +# View maintenance workflow runs +gh run list --workflow=agentics-maintenance.yml + +# Check for failures +gh run list --workflow=agentics-maintenance.yml --status=failure + +# View a specific run +gh run view RUN_ID +``` + +If expiration isn't working as expected: +- Verify the maintenance workflow is enabled +- Check workflow permissions (needs `issues: write` or `discussions: write`) +- Review failed runs for permission errors +- Ensure PAT tokens have appropriate scopes for cross-repository operations + +## Related Documentation + +- [Triggers Reference](/gh-aw/reference/triggers/) - Complete trigger configuration including `stop-after` +- [Safe Outputs Reference](/gh-aw/reference/safe-outputs/) - All safe output types and expiration options +- [SideRepoOps Guide](/gh-aw/guides/siderepoops/) - Complete setup for side repository operations +- [Security Best Practices](/gh-aw/guides/security/) - Authentication and security considerations +- [Campaign Workflows](/gh-aw/guides/campaigns/) - Orchestrating multi-workflow initiatives diff --git a/docs/src/content/docs/labs.mdx b/docs/src/content/docs/labs.mdx index d7b1152d3a..5e07d9ed4f 100644 --- a/docs/src/content/docs/labs.mdx +++ b/docs/src/content/docs/labs.mdx @@ -66,6 +66,7 @@ These are experimental agentic workflows used by the GitHub Next team to learn, | [Firewall Test Agent](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/firewall.md) | copilot | [![Firewall Test Agent](https://github.com/githubnext/gh-aw/actions/workflows/firewall.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/firewall.lock.yml) | - | - | | [GitHub MCP Remote Server Tools Report Generator](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/github-mcp-tools-report.md) | claude | [![GitHub MCP Remote Server Tools Report Generator](https://github.com/githubnext/gh-aw/actions/workflows/github-mcp-tools-report.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/github-mcp-tools-report.lock.yml) | - | - | | [GitHub MCP Structural Analysis](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/github-mcp-structural-analysis.md) | claude | [![GitHub MCP Structural Analysis](https://github.com/githubnext/gh-aw/actions/workflows/github-mcp-structural-analysis.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/github-mcp-structural-analysis.lock.yml) | `0 11 * * 1-5` | - | +| [GitHub Remote MCP Authentication Test](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/github-remote-mcp-auth-test.md) | copilot | [![GitHub Remote MCP Authentication Test](https://github.com/githubnext/gh-aw/actions/workflows/github-remote-mcp-auth-test.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/github-remote-mcp-auth-test.lock.yml) | - | - | | [Glossary Maintainer](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/glossary-maintainer.md) | copilot | [![Glossary Maintainer](https://github.com/githubnext/gh-aw/actions/workflows/glossary-maintainer.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/glossary-maintainer.lock.yml) | `0 10 * * 1-5` | - | | [Go Fan](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/go-fan.md) | claude | [![Go Fan](https://github.com/githubnext/gh-aw/actions/workflows/go-fan.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/go-fan.lock.yml) | `0 7 * * 1-5` | - | | [Go Logger Enhancement](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/go-logger.md) | claude | [![Go Logger Enhancement](https://github.com/githubnext/gh-aw/actions/workflows/go-logger.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/go-logger.lock.yml) | - | - | diff --git a/docs/src/content/docs/reference/safe-outputs.md b/docs/src/content/docs/reference/safe-outputs.md index b4d3723bcb..05fdb1ff96 100644 --- a/docs/src/content/docs/reference/safe-outputs.md +++ b/docs/src/content/docs/reference/safe-outputs.md @@ -64,7 +64,7 @@ Most safe output types support cross-repository operations. Exceptions are noted ### Security & Agent Tasks - [**Code Scanning Alerts**](#code-scanning-alerts-create-code-scanning-alert) (`create-code-scanning-alert`) — Generate SARIF security advisories (max: unlimited, same-repo only) -- [**Create Agent Session**](#agent-task-creation-create-agent-session) (`create-agent-session`) — Create Copilot agent sessions (max: 1) +- [**Create Agent Session**](#agent-session-creation-create-agent-session) (`create-agent-session`) — Create Copilot agent sessions (max: 1) ### System Types (Auto-Enabled)