diff --git a/.egg-state/contracts/389.json b/.egg-state/contracts/389.json new file mode 100644 index 0000000000..55a9d7b884 --- /dev/null +++ b/.egg-state/contracts/389.json @@ -0,0 +1,523 @@ +{ + "schemaVersion": "1.0", + "issue": { + "number": 389, + "title": "support releases", + "url": "https://github.com/jwbron/egg/issues/389" + }, + "current_phase": "implement", + "acceptance_criteria": [ + { + "id": "ac-1", + "description": "[TASK-1-1] On release v0.1.0, images are tagged as v0.1.0, v0.1, and v0", + "verified": false + }, + { + "id": "ac-2", + "description": "[TASK-1-2] Workflow fails gracefully if tag doesn't match vX.Y.Z pattern", + "verified": false + }, + { + "id": "ac-3", + "description": "[TASK-1-3] Tags with -alpha, -beta, -rc suffix don't update latest", + "verified": false + }, + { + "id": "ac-4", + "description": "[TASK-2-1] Script validates version format, creates git tag, updates floating tags (vX.Y, vX), and pushes to origin", + "verified": false + }, + { + "id": "ac-5", + "description": "[TASK-2-2] Dry-run shows what would happen without making changes", + "verified": false + }, + { + "id": "ac-6", + "description": "[TASK-2-3] Script outputs a markdown template suitable for GitHub release body", + "verified": false + }, + { + "id": "ac-7", + "description": "[TASK-3-1] All 5 uses jwbron/egg/action@main references updated to @v0", + "verified": false + }, + { + "id": "ac-8", + "description": "[TASK-3-2] uses line updated, action_ref input default updated", + "verified": false + }, + { + "id": "ac-9", + "description": "[TASK-3-3] uses line updated, action_ref input default updated", + "verified": false + }, + { + "id": "ac-10", + "description": "[TASK-3-4] uses line updated, action_ref input default updated", + "verified": false + }, + { + "id": "ac-11", + "description": "[TASK-3-5] uses line updated, action_ref input default updated", + "verified": false + }, + { + "id": "ac-12", + "description": "[TASK-3-6] uses line updated, action_ref input default updated", + "verified": false + }, + { + "id": "ac-13", + "description": "[TASK-3-7] uses line updated, action_ref input default updated", + "verified": false + }, + { + "id": "ac-14", + "description": "[TASK-3-8] uses line updated, action_ref input default updated", + "verified": false + }, + { + "id": "ac-15", + "description": "[TASK-4-1] Documents semver policy, how to pin versions, and what breaking changes mean", + "verified": false + }, + { + "id": "ac-16", + "description": "[TASK-4-2] Examples updated to use @v0, explanation of version pinning added", + "verified": false + }, + { + "id": "ac-17", + "description": "[TASK-4-3] Quick start example uses versioned reference", + "verified": false + }, + { + "id": "ac-18", + "description": "[TASK-4-4] Step-by-step guide for creating releases, including checklist", + "verified": false + }, + { + "id": "ac-19", + "description": "[TASK-5-1] CI green on main branch", + "verified": false + }, + { + "id": "ac-20", + "description": "[TASK-5-2] Git tags exist, GitHub release created, images pushed with version tags", + "verified": false + }, + { + "id": "ac-21", + "description": "[TASK-5-3] docker pull ghcr.io/jwbron/egg-sandbox:v0.1.0 succeeds", + "verified": false + } + ], + "phases": [ + { + "id": "phase-1", + "name": "Enhance Docker Image Tagging", + "status": "pending", + "tasks": [ + { + "id": "task-1-1", + "description": "Update release-images.yml to generate all tag variants (vX.Y.Z, vX.Y, vX)", + "status": "pending", + "acceptance_criteria": "On release v0.1.0, images are tagged as v0.1.0, v0.1, and v0", + "files_affected": [ + ".github/workflows/release-images.yml" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + }, + { + "id": "task-1-2", + "description": "Add validation to ensure release tags follow semver format", + "status": "pending", + "acceptance_criteria": "Workflow fails gracefully if tag doesn't match vX.Y.Z pattern", + "files_affected": [ + ".github/workflows/release-images.yml" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + }, + { + "id": "task-1-3", + "description": "Update workflow to skip latest tag update for pre-release versions", + "status": "pending", + "acceptance_criteria": "Tags with -alpha, -beta, -rc suffix don't update latest", + "files_affected": [ + ".github/workflows/release-images.yml" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + } + ], + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "escalation_reason": null, + "review_feedback": [] + }, + { + "id": "phase-2", + "name": "Create Release Automation Script", + "status": "pending", + "tasks": [ + { + "id": "task-2-1", + "description": "Create .github/scripts/create-release.sh script", + "status": "pending", + "acceptance_criteria": "Script validates version format, creates git tag, updates floating tags (vX.Y, vX), and pushes to origin", + "files_affected": [ + ".github/scripts/create-release.sh" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + }, + { + "id": "task-2-2", + "description": "Add --dry-run mode to script for testing", + "status": "pending", + "acceptance_criteria": "Dry-run shows what would happen without making changes", + "files_affected": [ + ".github/scripts/create-release.sh" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + }, + { + "id": "task-2-3", + "description": "Update script to generate release notes template", + "status": "pending", + "acceptance_criteria": "Script outputs a markdown template suitable for GitHub release body", + "files_affected": [ + ".github/scripts/create-release.sh" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + } + ], + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "escalation_reason": null, + "review_feedback": [] + }, + { + "id": "phase-3", + "name": "Update Action References", + "status": "pending", + "tasks": [ + { + "id": "task-3-1", + "description": "Update sdlc-pipeline.yml action references from @main to @v0", + "status": "pending", + "acceptance_criteria": "All 5 uses jwbron/egg/action@main references updated to @v0", + "files_affected": [ + ".github/workflows/sdlc-pipeline.yml" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + }, + { + "id": "task-3-2", + "description": "Update reusable-review.yml action reference", + "status": "pending", + "acceptance_criteria": "uses line updated, action_ref input default updated", + "files_affected": [ + ".github/workflows/reusable-review.yml" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + }, + { + "id": "task-3-3", + "description": "Update reusable-autofix.yml action reference", + "status": "pending", + "acceptance_criteria": "uses line updated, action_ref input default updated", + "files_affected": [ + ".github/workflows/reusable-autofix.yml" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + }, + { + "id": "task-3-4", + "description": "Update reusable-conflict-resolve.yml action reference", + "status": "pending", + "acceptance_criteria": "uses line updated, action_ref input default updated", + "files_affected": [ + ".github/workflows/reusable-conflict-resolve.yml" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + }, + { + "id": "task-3-5", + "description": "Update on-review-feedback.yml action reference", + "status": "pending", + "acceptance_criteria": "uses line updated, action_ref input default updated", + "files_affected": [ + ".github/workflows/on-review-feedback.yml" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + }, + { + "id": "task-3-6", + "description": "Update on-mention.yml action reference", + "status": "pending", + "acceptance_criteria": "uses line updated, action_ref input default updated", + "files_affected": [ + ".github/workflows/on-mention.yml" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + }, + { + "id": "task-3-7", + "description": "Update on-push-doc-updater.yml action reference", + "status": "pending", + "acceptance_criteria": "uses line updated, action_ref input default updated", + "files_affected": [ + ".github/workflows/on-push-doc-updater.yml" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + }, + { + "id": "task-3-8", + "description": "Update self-improvement.yml action reference", + "status": "pending", + "acceptance_criteria": "uses line updated, action_ref input default updated", + "files_affected": [ + ".github/workflows/self-improvement.yml" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + } + ], + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "escalation_reason": null, + "review_feedback": [] + }, + { + "id": "phase-4", + "name": "Update Documentation", + "status": "pending", + "tasks": [ + { + "id": "task-4-1", + "description": "Add versioning policy section to main README.md", + "status": "pending", + "acceptance_criteria": "Documents semver policy, how to pin versions, and what breaking changes mean", + "files_affected": [ + "README.md" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + }, + { + "id": "task-4-2", + "description": "Update docs/guides/reusable-workflows.md with versioning guidance", + "status": "pending", + "acceptance_criteria": "Examples updated to use @v0, explanation of version pinning added", + "files_affected": [ + "docs/guides/reusable-workflows.md" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + }, + { + "id": "task-4-3", + "description": "Update action/README.md with versioning examples", + "status": "pending", + "acceptance_criteria": "Quick start example uses versioned reference", + "files_affected": [ + "action/README.md" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + }, + { + "id": "task-4-4", + "description": "Create RELEASING.md documenting the release process", + "status": "pending", + "acceptance_criteria": "Step-by-step guide for creating releases, including checklist", + "files_affected": [ + "RELEASING.md" + ], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + } + ], + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "escalation_reason": null, + "review_feedback": [] + }, + { + "id": "phase-5", + "name": "Initial Release", + "status": "pending", + "tasks": [ + { + "id": "task-5-1", + "description": "Verify all tests pass on main", + "status": "pending", + "acceptance_criteria": "CI green on main branch", + "files_affected": [], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + }, + { + "id": "task-5-2", + "description": "Create v0.1.0 release using the release script", + "status": "pending", + "acceptance_criteria": "Git tags exist, GitHub release created, images pushed with version tags", + "files_affected": [], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + }, + { + "id": "task-5-3", + "description": "Verify versioned images are accessible", + "status": "pending", + "acceptance_criteria": "docker pull ghcr.io/jwbron/egg-sandbox:v0.1.0 succeeds", + "files_affected": [], + "commit": null, + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "notes": "" + } + ], + "review_cycles": 0, + "max_cycles": 3, + "escalated": false, + "escalation_reason": null, + "review_feedback": [] + } + ], + "decisions": [], + "circuit_breaker": { + "total_cycles": 0, + "max_total_cycles": 10, + "status": "closed" + }, + "workflow_owner": "jwbron", + "audit_log": [ + { + "timestamp": "2026-02-09T06:22:41Z", + "actor": "system", + "role": "reviewer", + "action": "update", + "field_path": "refine_review_cycles", + "old_value": 0, + "new_value": 1, + "reason": "Refine review cycle 1: approved" + }, + { + "timestamp": "2026-02-09T06:47:12Z", + "actor": "jwbron", + "role": "human", + "action": "transition", + "field_path": "current_phase", + "old_value": "refine", + "new_value": "plan", + "reason": "Phase approved by human" + }, + { + "timestamp": "2026-02-09T06:54:11Z", + "actor": "system", + "role": "reviewer", + "action": "update", + "field_path": "plan_review_cycles", + "old_value": 0, + "new_value": 1, + "reason": "Plan review cycle 1: approved" + }, + { + "timestamp": "2026-02-10T04:38:48Z", + "actor": "jwbron", + "role": "human", + "action": "transition", + "field_path": "current_phase", + "old_value": "plan", + "new_value": "implement", + "reason": "Phase approved by human" + } + ], + "refine_review_cycles": 1, + "refine_review_feedback": "", + "plan_review_cycles": 1, + "plan_review_feedback": "", + "pr": { + "title": "Add semantic versioning for releases", + "description": "Implements semantic versioning for Docker images and GitHub Action references.\nThis enables version pinning for stability and rollback capability.\n\nKey changes:\n- Release workflow produces vX.Y.Z, vX.Y, and vX tags for images\n- All internal action references pinned to @v0\n- Helper script for creating releases with proper tag management\n- Documentation for versioning policy and release process\n\nCloses #389" + } +} diff --git a/.egg-state/drafts/389-analysis.md b/.egg-state/drafts/389-analysis.md new file mode 100644 index 0000000000..1cd0f9a805 --- /dev/null +++ b/.egg-state/drafts/389-analysis.md @@ -0,0 +1,178 @@ +# Analysis: Support Releases + +> Issue: #389 | Phase: refine + +## Problem Statement + +The egg project currently lacks a formal release versioning strategy. Docker images are built and pushed to GHCR on every push to `main` with the `latest` tag, and workflows reference the action via `@main`. This creates challenges: + +1. **No rollback capability**: If a breaking change is deployed, there's no easy way to pin to a known-good version +2. **No version stability**: Consumers of the reusable workflows and Docker images have no guarantee of stability +3. **No changelog tracking**: There's no formal record of what changed between versions + +The desired outcome is a tagging system for both Docker images and GitHub workflow references that enables: +- Pinning to specific versions for stability +- Creating releases with changelogs +- Rolling back to previous versions when needed + +## Current Behavior + +### Docker Images + +The `release-images.yml` workflow (`.github/workflows/release-images.yml:1-70`) builds and pushes two images: +- `ghcr.io/jwbron/egg-gateway` +- `ghcr.io/jwbron/egg-sandbox` + +Current tagging logic: +- On push to `main`: Tags as `latest` +- On release publish: Tags with release tag name AND `latest` +- On workflow_dispatch: Tags with input tag AND `latest` + +The action supports an `image-tag` input (`action/action.yml:50-53`) that defaults to `latest`, which allows consumers to pin to specific image versions. + +### Workflow References + +There are two categories of workflow references: + +**1. Internal reusable workflows** (within this repo): +```yaml +uses: ./.github/workflows/reusable-review.yml +``` +These are always pinned to the current branch/commit since they use relative paths. + +**2. Action references** (used by this repo and external consumers): +```yaml +uses: jwbron/egg/action@main +``` +Found in: +- `reusable-review.yml:464` +- `reusable-autofix.yml:176` +- `reusable-conflict-resolve.yml:178` +- `sdlc-pipeline.yml:516, 1277, 1483, 1919` +- `on-mention.yml:298` +- `on-push-doc-updater.yml:102` +- `on-review-feedback.yml:399` + +All action references currently point to `@main`, which means any push to main immediately affects all running workflows. + +### Dependencies + +The issue notes this "depends on reusable workflows being implemented" - reviewing the codebase shows reusable workflows ARE already implemented: +- `reusable-review.yml` +- `reusable-autofix.yml` +- `reusable-conflict-resolve.yml` + +These are called from other workflows using `uses: ./.github/workflows/reusable-*.yml`. + +## Constraints + +- **GitHub Actions limitation**: The `uses:` field cannot be dynamic - it must be a literal string, so action references cannot be parameterized +- **Image tag propagation**: When creating a release, the action and workflows must agree on which image tag to use +- **Backwards compatibility**: Existing consumers using `@main` should continue to work +- **Dependabot**: Already configured for GitHub Actions version updates, which will help keep pinned versions current + +## Options Considered + +### Option A: Semantic Version Tags with Major Version Aliases + +**Approach**: Use semantic versioning (v1.0.0, v1.0.1, etc.) with major version tags (v1, v2) that float to the latest minor/patch release. + +Create releases like `v1.0.0` which: +- Build images tagged as `v1.0.0` and update floating `v1` tag +- Create git tag `v1.0.0` and update floating `v1` tag +- Workflows would reference `@v1` for stability with automatic minor/patch updates + +**Pros**: +- Industry standard approach (used by actions/checkout, docker/build-push-action) +- Clear semantic meaning of version bumps +- Major version tags provide stability with security updates +- Dependabot can detect and PR version updates + +**Cons**: +- Requires discipline to follow semver correctly +- Need to maintain floating tags (v1 → v1.x.y) +- More complex release process + +### Option B: Simple Sequential Tags + +**Approach**: Use simple sequential version numbers (v1, v2, v3) without floating tags. Each release is a complete version. + +**Pros**: +- Simple to understand and maintain +- No floating tag management +- Clear lineage + +**Cons**: +- No semantic meaning to version bumps +- Must update all references for any change +- More frequent dependabot PRs + +### Option C: Date-Based Tags + +**Approach**: Use date-based tags (2025.01, 2025.02) with monthly releases. + +**Pros**: +- Clear timeline of when changes occurred +- Predictable release cadence + +**Cons**: +- No indication of breaking vs non-breaking changes +- Unusual pattern for GitHub Actions +- Forced monthly releases may not align with development + +## Recommended Approach + +**Option A: Semantic Version Tags with Major Version Aliases** is recommended. + +Justification: +1. **Industry standard**: This is how major GitHub Actions are versioned (actions/checkout@v4, docker/build-push-action@v6) +2. **Balances stability and updates**: Consumers can pin to `@v1` and get patches/minor updates, or pin to `@v1.2.3` for exact reproducibility +3. **Dependabot integration**: Works well with existing dependabot config - will detect major version bumps +4. **Clear communication**: Version numbers communicate the impact of changes + +### Implementation Sketch + +1. **Modify `release-images.yml`** to: + - On release `vX.Y.Z`: Tag images as `vX.Y.Z`, `vX.Y`, and `vX` + - Keep `latest` as an alias to the most recent release + +2. **Update action references** in all workflows from `@main` to `@v1` (after first release) + +3. **Create release workflow** or document release process: + - Tag the release: `git tag v1.0.0 && git push origin v1.0.0` + - Create GitHub release (triggers image build) + - Update floating major tag: `git tag -f v1 v1.0.0 && git push -f origin v1` + +4. **Document versioning policy** in README: + - Major: Breaking changes to action inputs, workflow behavior, or image interfaces + - Minor: New features, backward-compatible changes + - Patch: Bug fixes, security updates + +## Open Questions + +**Multiple-choice: Release automation level** + +How automated should the release process be? + +- [ ] **Fully manual**: Human creates GitHub release, images auto-build, human updates floating tags +- [ ] **Semi-automated**: Human creates release, automation handles all tagging (images + git floating tags) +- [ ] **Fully automated**: Semantic-release or similar tool determines version from commit messages and creates releases automatically +- [ ] Other (explain in reply) + +**Multiple-choice: Initial version number** + +What should the first release version be? + +- [ ] **v0.1.0**: Indicates pre-1.0 stability, allows breaking changes without major bumps +- [ ] **v1.0.0**: Indicates production readiness, follows strict semver from start +- [ ] Other (explain in reply) + +**Open-ended questions**: + +1. Are there any external consumers of the action/workflows that we need to coordinate with for the version cutover? + +2. Should we maintain a CHANGELOG.md file, or rely solely on GitHub release notes? + +--- + +*Authored-by: egg* diff --git a/.egg-state/drafts/389-plan.md b/.egg-state/drafts/389-plan.md new file mode 100644 index 0000000000..afafa742bb --- /dev/null +++ b/.egg-state/drafts/389-plan.md @@ -0,0 +1,286 @@ +# Plan: Support Releases + +> Issue: #389 | Phase: plan + +## Summary + +This plan implements semantic versioning for the egg project, enabling version-pinned Docker images and GitHub Action references. Based on the approved analysis, we'll use semantic versioning with major version aliases (v1, v2) and a semi-automated release process starting at v0.1.0. + +The implementation modifies the release workflow to produce versioned tags (vX.Y.Z, vX.Y, vX), updates all action references from `@main` to `@v0`, and creates a documented release process with a helper script. + +## Implementation Phases + +### Phase 1: Enhance Docker Image Tagging + +**Goal**: Modify the release workflow to produce semantic version tags with floating major/minor aliases. + +**Tasks**: +- [TASK-1-1] Update `release-images.yml` to generate all tag variants (vX.Y.Z, vX.Y, vX) — Acceptance: On release `v0.1.0`, images are tagged as `v0.1.0`, `v0.1`, and `v0` +- [TASK-1-2] Add validation to ensure release tags follow semver format — Acceptance: Workflow fails gracefully if tag doesn't match `vX.Y.Z` pattern +- [TASK-1-3] Update workflow to skip `latest` tag update for pre-release versions — Acceptance: Tags with `-alpha`, `-beta`, `-rc` suffix don't update `latest` + +**Dependencies**: None + +**Exit criteria**: Workflow can be manually triggered with a semver tag and produces all expected image tags. + +### Phase 2: Create Release Automation Script + +**Goal**: Provide a semi-automated release script that handles git tagging and floating tag updates. + +**Tasks**: +- [TASK-2-1] Create `.github/scripts/create-release.sh` script — Acceptance: Script validates version format, creates git tag, updates floating tags (vX.Y, vX), and pushes to origin +- [TASK-2-2] Add `--dry-run` mode to script for testing — Acceptance: Dry-run shows what would happen without making changes +- [TASK-2-3] Update script to generate release notes template — Acceptance: Script outputs a markdown template suitable for GitHub release body + +**Dependencies**: Phase 1 (need updated workflow to consume the tags) + +**Exit criteria**: Running `./github/scripts/create-release.sh v0.1.0` creates the release with all necessary tags. + +### Phase 3: Update Action References + +**Goal**: Pin all workflow action references to the `@v0` floating tag. + +**Tasks**: +- [TASK-3-1] Update `sdlc-pipeline.yml` action references from `@main` to `@v0` — Acceptance: All 5 `uses: jwbron/egg/action@main` references updated to `@v0` +- [TASK-3-2] Update `reusable-review.yml` action reference — Acceptance: `uses:` line updated, `action_ref` input default updated +- [TASK-3-3] Update `reusable-autofix.yml` action reference — Acceptance: `uses:` line updated, `action_ref` input default updated +- [TASK-3-4] Update `reusable-conflict-resolve.yml` action reference — Acceptance: `uses:` line updated, `action_ref` input default updated +- [TASK-3-5] Update `on-review-feedback.yml` action reference — Acceptance: `uses:` line updated, `action_ref` input default updated +- [TASK-3-6] Update `on-mention.yml` action reference — Acceptance: `uses:` line updated, `action_ref` input default updated +- [TASK-3-7] Update `on-push-doc-updater.yml` action reference — Acceptance: `uses:` line updated, `action_ref` input default updated +- [TASK-3-8] Update `self-improvement.yml` action reference — Acceptance: `uses:` line updated, `action_ref` input default updated + +**Dependencies**: Phase 1 and 2 complete; v0.1.0 release must be created before merging this phase + +**Exit criteria**: All action references point to `@v0`, and workflows continue to function correctly. + +### Phase 4: Update Documentation + +**Goal**: Document the versioning policy and release process. + +**Tasks**: +- [TASK-4-1] Add versioning policy section to main README.md — Acceptance: Documents semver policy, how to pin versions, and what breaking changes mean +- [TASK-4-2] Update `docs/guides/reusable-workflows.md` with versioning guidance — Acceptance: Examples updated to use `@v0`, explanation of version pinning added +- [TASK-4-3] Update `action/README.md` with versioning examples — Acceptance: Quick start example uses versioned reference +- [TASK-4-4] Create `RELEASING.md` documenting the release process — Acceptance: Step-by-step guide for creating releases, including checklist + +**Dependencies**: Phases 1-3 complete + +**Exit criteria**: Documentation accurately reflects the versioning system and release process. + +### Phase 5: Initial Release + +**Goal**: Create the v0.1.0 release to enable versioned references. + +**Tasks**: +- [TASK-5-1] Verify all tests pass on main — Acceptance: CI green on main branch +- [TASK-5-2] Create v0.1.0 release using the release script — Acceptance: Git tags exist, GitHub release created, images pushed with version tags +- [TASK-5-3] Verify versioned images are accessible — Acceptance: `docker pull ghcr.io/jwbron/egg-sandbox:v0.1.0` succeeds + +**Dependencies**: Phases 1-4 merged to main + +**Exit criteria**: v0.1.0 release published, versioned images available, workflows using `@v0` function correctly. + +## Test Strategy + +- **Unit tests**: None required (shell scripts don't have unit tests in this repo) +- **Integration tests**: + - `test-action.yml` workflow validates the action works correctly + - Manual test of `create-release.sh --dry-run` before actual release +- **Manual testing**: + 1. After Phase 1: Trigger workflow_dispatch with test tag, verify all expected image tags appear in GHCR + 2. After Phase 2: Run `create-release.sh --dry-run v0.0.0-test` to validate script behavior + 3. After Phase 3: Verify workflows still reference correct action (grep for `@v0`) + 4. After Phase 5: Run a full SDLC pipeline on a test issue to validate end-to-end + +## Rollback Plan + +**If image tagging breaks**: +1. Revert changes to `release-images.yml` +2. Re-push images with `latest` tag: `docker push ghcr.io/jwbron/egg-sandbox:latest` + +**If action references break workflows**: +1. Revert action references from `@v0` to `@main` +2. Force-push `v0` tag to a known-good commit: `git tag -f v0 && git push -f origin v0` + +**If release script creates bad tags**: +1. Delete bad tags: `git push --delete origin v0.1.0 v0.1 v0` +2. Delete local tags: `git tag -d v0.1.0 v0.1 v0` +3. Fix script and retry + +## Risk Assessment + +| Risk | Likelihood | Impact | Mitigation | +|------|------------|--------|------------| +| Workflows break when switching from @main to @v0 | Low | High | Create release before updating references; test in fork first | +| Force-push of floating tags (v0) causes issues | Medium | Low | Document that floating tags are updated on each release; use specific versions (v0.1.0) for reproducibility | +| Release script creates incorrect tags | Low | Medium | Dry-run mode for validation; tag validation in script | +| External consumers break on version change | Low | Low | Maintain @main as alias during transition; document in release notes | + +## Migration Notes + +**For external consumers of egg workflows**: +- Current `@main` references will continue to work +- Recommend updating to `@v0` for stability with automatic updates +- Use specific versions like `@v0.1.0` for full reproducibility +- Dependabot will detect major version updates automatically + +**Order of operations for initial release**: +1. Merge Phases 1-2 (image tagging + release script) +2. Create v0.1.0 release using new script +3. Merge Phases 3-4 (update references + documentation) +4. Complete Phase 5 verification + +This sequencing ensures versioned images exist before workflows reference them. + +--- + +## Structured Task Appendix + +The following YAML block is machine-readable and will be extracted into the contract. +It must accurately reflect the tasks described above. The `pr:` section provides the +title and description that will be used when creating the pull request. + +```yaml +# yaml-tasks +pr: + title: "Add semantic versioning for releases" + description: | + Implements semantic versioning for Docker images and GitHub Action references. + This enables version pinning for stability and rollback capability. + + Key changes: + - Release workflow produces vX.Y.Z, vX.Y, and vX tags for images + - All internal action references pinned to @v0 + - Helper script for creating releases with proper tag management + - Documentation for versioning policy and release process + + Closes #389 +phases: + - id: 1 + name: Enhance Docker Image Tagging + goal: Modify the release workflow to produce semantic version tags with floating major/minor aliases + tasks: + - id: TASK-1-1 + description: Update release-images.yml to generate all tag variants (vX.Y.Z, vX.Y, vX) + acceptance: On release v0.1.0, images are tagged as v0.1.0, v0.1, and v0 + files: + - .github/workflows/release-images.yml + - id: TASK-1-2 + description: Add validation to ensure release tags follow semver format + acceptance: Workflow fails gracefully if tag doesn't match vX.Y.Z pattern + files: + - .github/workflows/release-images.yml + - id: TASK-1-3 + description: Update workflow to skip latest tag update for pre-release versions + acceptance: Tags with -alpha, -beta, -rc suffix don't update latest + files: + - .github/workflows/release-images.yml + - id: 2 + name: Create Release Automation Script + goal: Provide a semi-automated release script that handles git tagging and floating tag updates + tasks: + - id: TASK-2-1 + description: Create .github/scripts/create-release.sh script + acceptance: Script validates version format, creates git tag, updates floating tags (vX.Y, vX), and pushes to origin + files: + - .github/scripts/create-release.sh + - id: TASK-2-2 + description: Add --dry-run mode to script for testing + acceptance: Dry-run shows what would happen without making changes + files: + - .github/scripts/create-release.sh + - id: TASK-2-3 + description: Update script to generate release notes template + acceptance: Script outputs a markdown template suitable for GitHub release body + files: + - .github/scripts/create-release.sh + - id: 3 + name: Update Action References + goal: Pin all workflow action references to the @v0 floating tag + tasks: + - id: TASK-3-1 + description: Update sdlc-pipeline.yml action references from @main to @v0 + acceptance: All 5 uses jwbron/egg/action@main references updated to @v0 + files: + - .github/workflows/sdlc-pipeline.yml + - id: TASK-3-2 + description: Update reusable-review.yml action reference + acceptance: uses line updated, action_ref input default updated + files: + - .github/workflows/reusable-review.yml + - id: TASK-3-3 + description: Update reusable-autofix.yml action reference + acceptance: uses line updated, action_ref input default updated + files: + - .github/workflows/reusable-autofix.yml + - id: TASK-3-4 + description: Update reusable-conflict-resolve.yml action reference + acceptance: uses line updated, action_ref input default updated + files: + - .github/workflows/reusable-conflict-resolve.yml + - id: TASK-3-5 + description: Update on-review-feedback.yml action reference + acceptance: uses line updated, action_ref input default updated + files: + - .github/workflows/on-review-feedback.yml + - id: TASK-3-6 + description: Update on-mention.yml action reference + acceptance: uses line updated, action_ref input default updated + files: + - .github/workflows/on-mention.yml + - id: TASK-3-7 + description: Update on-push-doc-updater.yml action reference + acceptance: uses line updated, action_ref input default updated + files: + - .github/workflows/on-push-doc-updater.yml + - id: TASK-3-8 + description: Update self-improvement.yml action reference + acceptance: uses line updated, action_ref input default updated + files: + - .github/workflows/self-improvement.yml + - id: 4 + name: Update Documentation + goal: Document the versioning policy and release process + tasks: + - id: TASK-4-1 + description: Add versioning policy section to main README.md + acceptance: Documents semver policy, how to pin versions, and what breaking changes mean + files: + - README.md + - id: TASK-4-2 + description: Update docs/guides/reusable-workflows.md with versioning guidance + acceptance: Examples updated to use @v0, explanation of version pinning added + files: + - docs/guides/reusable-workflows.md + - id: TASK-4-3 + description: Update action/README.md with versioning examples + acceptance: Quick start example uses versioned reference + files: + - action/README.md + - id: TASK-4-4 + description: Create RELEASING.md documenting the release process + acceptance: Step-by-step guide for creating releases, including checklist + files: + - RELEASING.md + - id: 5 + name: Initial Release + goal: Create the v0.1.0 release to enable versioned references + tasks: + - id: TASK-5-1 + description: Verify all tests pass on main + acceptance: CI green on main branch + files: [] + - id: TASK-5-2 + description: Create v0.1.0 release using the release script + acceptance: Git tags exist, GitHub release created, images pushed with version tags + files: [] + - id: TASK-5-3 + description: Verify versioned images are accessible + acceptance: docker pull ghcr.io/jwbron/egg-sandbox:v0.1.0 succeeds + files: [] +``` + +--- + +*Authored-by: egg* diff --git a/.github/scripts/create-release.sh b/.github/scripts/create-release.sh new file mode 100755 index 0000000000..8bb5abcae6 --- /dev/null +++ b/.github/scripts/create-release.sh @@ -0,0 +1,260 @@ +#!/usr/bin/env bash +# +# create-release.sh - Create a new release with semantic versioning +# +# Usage: ./create-release.sh [--dry-run] +# +# Examples: +# ./create-release.sh v0.1.0 # Create release v0.1.0 +# ./create-release.sh --dry-run v1.0.0 # Show what would happen +# +# This script: +# 1. Validates the version follows semver (vX.Y.Z) +# 2. Creates the version tag (v0.1.0) +# 3. Updates/creates floating tags (v0.1, v0) +# 4. Pushes all tags to origin +# 5. Outputs a release notes template + +set -euo pipefail + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +DRY_RUN=false +VERSION="" + +usage() { + echo "Usage: $0 [--dry-run] " + echo "" + echo "Options:" + echo " --dry-run Show what would happen without making changes" + echo "" + echo "Arguments:" + echo " version Semantic version (e.g., v0.1.0, v1.0.0-beta)" + echo "" + echo "Examples:" + echo " $0 v0.1.0" + echo " $0 --dry-run v1.0.0" + exit 1 +} + +log_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +log_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +log_warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" >&2 +} + +run_cmd() { + if [[ "$DRY_RUN" == "true" ]]; then + echo -e "${YELLOW}[DRY-RUN]${NC} Would run: $*" + else + "$@" + fi +} + +# Parse arguments +while [[ $# -gt 0 ]]; do + case "$1" in + --dry-run) + DRY_RUN=true + shift + ;; + -h|--help) + usage + ;; + -*) + log_error "Unknown option: $1" + usage + ;; + *) + if [[ -z "$VERSION" ]]; then + VERSION="$1" + else + log_error "Unexpected argument: $1" + usage + fi + shift + ;; + esac +done + +if [[ -z "$VERSION" ]]; then + log_error "Version is required" + usage +fi + +# Validate semver format +if [[ ! "$VERSION" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)(-[a-zA-Z0-9.]+)?$ ]]; then + log_error "Invalid version format: $VERSION" + echo "Version must match semver: vX.Y.Z or vX.Y.Z-prerelease" + echo "Examples: v0.1.0, v1.0.0, v2.0.0-beta, v1.0.0-rc.1" + exit 1 +fi + +MAJOR="${BASH_REMATCH[1]}" +MINOR="${BASH_REMATCH[2]}" +PATCH="${BASH_REMATCH[3]}" +PRERELEASE="${BASH_REMATCH[4]}" + +MAJOR_TAG="v${MAJOR}" +MINOR_TAG="v${MAJOR}.${MINOR}" + +IS_PRERELEASE=false +if [[ -n "$PRERELEASE" ]]; then + IS_PRERELEASE=true +fi + +# Check we're in a git repo +if ! git rev-parse --git-dir > /dev/null 2>&1; then + log_error "Not in a git repository" + exit 1 +fi + +# Check for uncommitted changes +if ! git diff-index --quiet HEAD -- 2>/dev/null; then + log_error "There are uncommitted changes. Please commit or stash them first." + exit 1 +fi + +# Fetch latest tags +log_info "Fetching latest tags from origin..." +if [[ "$DRY_RUN" != "true" ]]; then + git fetch --tags origin +fi + +# Check if version tag already exists +if git rev-parse "$VERSION" > /dev/null 2>&1; then + log_error "Tag $VERSION already exists" + exit 1 +fi + +# Get current commit +CURRENT_SHA=$(git rev-parse HEAD) +CURRENT_SHA_SHORT=$(git rev-parse --short HEAD) + +echo "" +log_info "Release Configuration:" +echo " Version: $VERSION" +echo " Major tag: $MAJOR_TAG" +echo " Minor tag: $MINOR_TAG" +echo " Commit: $CURRENT_SHA_SHORT" +echo " Pre-release: $IS_PRERELEASE" +echo "" + +if [[ "$DRY_RUN" == "true" ]]; then + log_warn "DRY-RUN MODE - No changes will be made" + echo "" +fi + +# Create the version tag +log_info "Creating tag $VERSION..." +run_cmd git tag -a "$VERSION" -m "Release $VERSION" + +# Update floating tags (force update if they exist) +log_info "Updating floating tag $MINOR_TAG..." +run_cmd git tag -f "$MINOR_TAG" -m "Floating tag for $MAJOR.$MINOR.x releases" + +log_info "Updating floating tag $MAJOR_TAG..." +run_cmd git tag -f "$MAJOR_TAG" -m "Floating tag for $MAJOR.x.x releases" + +# Push tags +log_info "Pushing tags to origin..." +run_cmd git push origin "$VERSION" +run_cmd git push -f origin "$MINOR_TAG" +run_cmd git push -f origin "$MAJOR_TAG" + +echo "" +if [[ "$DRY_RUN" == "true" ]]; then + log_success "Dry run complete. Run without --dry-run to create the release." +else + log_success "Tags created and pushed successfully!" +fi + +# Generate release notes template +echo "" +echo "==========================================" +echo "Release Notes Template" +echo "==========================================" +echo "" + +# Get commits since last tag (or all if no tags) +PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "") + +cat << EOF +## $VERSION + +### Highlights + + + +### Changes + +EOF + +if [[ -n "$PREV_TAG" ]]; then + echo "" + if [[ "$DRY_RUN" != "true" ]]; then + git log --oneline "$PREV_TAG"..HEAD | sed 's/^/- /' + else + echo "" + fi +else + echo "" + if [[ "$DRY_RUN" != "true" ]]; then + git log --oneline -10 | sed 's/^/- /' + echo "" + fi +fi + +cat << EOF + +### Docker Images + +\`\`\`bash +docker pull ghcr.io/jwbron/egg-sandbox:$VERSION +docker pull ghcr.io/jwbron/egg-gateway:$VERSION +\`\`\` + +### Versioned References + +For stability, pin to the major version: +\`\`\`yaml +uses: jwbron/egg/action@$MAJOR_TAG +\`\`\` + +For full reproducibility: +\`\`\`yaml +uses: jwbron/egg/action@$VERSION +\`\`\` +EOF + +if [[ "$IS_PRERELEASE" == "true" ]]; then + echo "" + echo "---" + echo "**Note:** This is a pre-release version ($PRERELEASE)." +fi + +echo "" +echo "==========================================" + +if [[ "$DRY_RUN" != "true" ]]; then + echo "" + log_info "Next steps:" + echo " 1. Go to: https://github.com/jwbron/egg/releases/new?tag=$VERSION" + echo " 2. Copy the release notes template above" + echo " 3. Edit and publish the release" +fi diff --git a/.github/workflows/release-images.yml b/.github/workflows/release-images.yml index d42bd5e837..927e8391da 100644 --- a/.github/workflows/release-images.yml +++ b/.github/workflows/release-images.yml @@ -43,17 +43,78 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Set image tag - id: tag + - name: Validate and parse version tag + id: version run: | + TAG="" + IS_RELEASE="false" + IS_PRERELEASE="false" + if [[ "${{ github.event_name }}" == "release" ]]; then - echo "tag=${{ github.event.release.tag_name }}" >> "$GITHUB_OUTPUT" + TAG="${{ github.event.release.tag_name }}" + IS_RELEASE="true" elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - echo "tag=${{ inputs.tag }}" >> "$GITHUB_OUTPUT" + TAG="${{ inputs.tag }}" + # Treat workflow_dispatch with semver tag as a release + if [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+ ]]; then + IS_RELEASE="true" + fi else - echo "tag=latest" >> "$GITHUB_OUTPUT" + TAG="latest" + fi + + # Validate semver format for releases + if [[ "$IS_RELEASE" == "true" ]]; then + if [[ ! "$TAG" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)(-[a-zA-Z0-9.]+)?$ ]]; then + echo "::error::Invalid version tag '$TAG'. Must match semver format: vX.Y.Z or vX.Y.Z-prerelease" + exit 1 + fi + + MAJOR="${BASH_REMATCH[1]}" + MINOR="${BASH_REMATCH[2]}" + PRERELEASE="${BASH_REMATCH[4]}" + + echo "major_tag=v${MAJOR}" >> "$GITHUB_OUTPUT" + echo "minor_tag=v${MAJOR}.${MINOR}" >> "$GITHUB_OUTPUT" + + # Check for pre-release suffix (-alpha, -beta, -rc, etc.) + if [[ -n "$PRERELEASE" ]]; then + IS_PRERELEASE="true" + fi + fi + + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + echo "is_release=$IS_RELEASE" >> "$GITHUB_OUTPUT" + echo "is_prerelease=$IS_PRERELEASE" >> "$GITHUB_OUTPUT" + + - name: Generate image tags + id: tags + run: | + IMAGE="${{ matrix.image }}" + TAG="${{ steps.version.outputs.tag }}" + IS_RELEASE="${{ steps.version.outputs.is_release }}" + IS_PRERELEASE="${{ steps.version.outputs.is_prerelease }}" + MAJOR_TAG="${{ steps.version.outputs.major_tag }}" + MINOR_TAG="${{ steps.version.outputs.minor_tag }}" + + TAGS="${IMAGE}:${TAG}" + + if [[ "$IS_RELEASE" == "true" ]]; then + # Add floating version tags (vX.Y, vX) + TAGS="${TAGS},${IMAGE}:${MINOR_TAG},${IMAGE}:${MAJOR_TAG}" + + # Add latest tag only for stable releases (not pre-releases) + if [[ "$IS_PRERELEASE" == "false" ]]; then + TAGS="${TAGS},${IMAGE}:latest" + fi + elif [[ "$TAG" != "latest" ]]; then + # Non-release push to main: add latest tag + TAGS="${TAGS},${IMAGE}:latest" fi + echo "tags=$TAGS" >> "$GITHUB_OUTPUT" + echo "Generated tags: $TAGS" + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -64,6 +125,4 @@ jobs: file: ${{ matrix.dockerfile }} push: true platforms: linux/amd64 - tags: | - ${{ matrix.image }}:${{ steps.tag.outputs.tag }} - ${{ matrix.image }}:latest + tags: ${{ steps.tags.outputs.tags }} diff --git a/README.md b/README.md index 0650f80a6c..e0e7d0d2c5 100644 --- a/README.md +++ b/README.md @@ -183,7 +183,7 @@ See the [Deployment Guide](docs/guides/deployment.md) for production deployment egg can run as a GitHub Action for CI/CD automation: ```yaml -- uses: jwbron/egg@main +- uses: jwbron/egg/action@v0 with: prompt: "Fix the failing tests" anthropic-oauth-token: ${{ secrets.ANTHROPIC_OAUTH_TOKEN }} @@ -263,6 +263,42 @@ See [GitHub Action documentation](action/README.md) for details. - [Contributing](CONTRIBUTING.md) — Development setup and workflow - [Why egg Works](docs/collaboration-effectiveness.md) — Safety, quality, and collaboration +## Versioning + +egg uses [semantic versioning](https://semver.org/) for both Docker images and GitHub Action references. + +### Version Pinning + +For stability, pin to a major version: +```yaml +uses: jwbron/egg/action@v0 # Receives all v0.x.y updates +``` + +For full reproducibility: +```yaml +uses: jwbron/egg/action@v0.1.0 # Exact version +``` + +### Docker Images + +```bash +# Latest stable (updated on every release) +docker pull ghcr.io/jwbron/egg-sandbox:latest + +# Major version (updated on v0.x.y releases) +docker pull ghcr.io/jwbron/egg-sandbox:v0 + +# Exact version +docker pull ghcr.io/jwbron/egg-sandbox:v0.1.0 +``` + +### Breaking Changes + +- **v0.x.y**: Pre-stable releases. Minor versions may contain breaking changes. +- **v1.x.y and later**: Stable releases. Breaking changes only in major version bumps. + +See [RELEASING.md](RELEASING.md) for the release process. + ## Development ```bash diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 0000000000..1840b4d9cf --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,136 @@ +# Releasing + +This document describes the release process for egg. + +## Version Scheme + +egg uses [semantic versioning](https://semver.org/): + +- **Major version (vX.0.0)**: Breaking changes to workflows, action inputs/outputs, or gateway API +- **Minor version (v0.X.0)**: New features, backward-compatible enhancements +- **Patch version (v0.0.X)**: Bug fixes, documentation updates + +### Pre-1.0 Releases + +During the v0.x.y phase, minor versions may contain breaking changes. Pin to exact versions for maximum stability. + +### Pre-release Versions + +Use suffixes for pre-release versions: +- `-alpha.N`: Early development, may be unstable +- `-beta.N`: Feature complete, seeking feedback +- `-rc.N`: Release candidate, final testing + +Pre-release versions do not update the `latest` Docker tag. + +## Release Artifacts + +Each release produces: + +| Artifact | Tags | +|----------|------| +| Docker images | `vX.Y.Z`, `vX.Y`, `vX`, `latest` (stable only) | +| Git tags | `vX.Y.Z`, `vX.Y`, `vX` (floating) | +| GitHub Release | `vX.Y.Z` with changelog | + +## Creating a Release + +### Prerequisites + +- All tests passing on main +- No critical open issues +- CHANGELOG.md updated (if applicable) + +### Using the Release Script + +```bash +# Dry run first +.github/scripts/create-release.sh --dry-run v0.2.0 + +# Create the release +.github/scripts/create-release.sh v0.2.0 +``` + +The script will: +1. Validate the version format +2. Create the version tag (v0.2.0) +3. Update floating tags (v0.2, v0) +4. Push all tags to origin +5. Output a release notes template + +### Creating the GitHub Release + +After running the script: + +1. Go to https://github.com/jwbron/egg/releases/new?tag=vX.Y.Z +2. Copy the release notes template from the script output +3. Edit the highlights and changelog sections +4. For pre-release versions, check "Set as a pre-release" +5. Publish the release + +The `release-images.yml` workflow will automatically build and push Docker images with all version tags. + +## Release Checklist + +Before releasing: + +- [ ] All CI checks passing on main +- [ ] Version number follows semver +- [ ] Breaking changes documented (if any) +- [ ] Migration notes included for breaking changes + +During release: + +- [ ] Run `create-release.sh --dry-run` to verify +- [ ] Run `create-release.sh` to create and push tags +- [ ] Create GitHub release with changelog +- [ ] Verify Docker images are pushed + +After release: + +- [ ] Verify `docker pull ghcr.io/jwbron/egg-sandbox:vX.Y.Z` works +- [ ] Verify `@vX` floating tag is updated +- [ ] Notify users of breaking changes (if any) + +## Rollback + +### Bad Release + +If a release is broken: + +```bash +# Delete the bad tags +git push --delete origin v0.2.0 v0.2 v0 +git tag -d v0.2.0 v0.2 v0 + +# Point floating tags to the last good release +git tag -f v0.2 v0.1.5 +git tag -f v0 v0.1.5 +git push -f origin v0.2 v0 +``` + +### Emergency Hotfix + +For critical bugs in a released version: + +1. Create a hotfix branch from the release tag +2. Fix the issue +3. Release as vX.Y.Z+1 patch version +4. Floating tags will update automatically + +## Dependabot + +External consumers using Dependabot will receive automatic PRs when: +- New major versions are released (requires manual merge) +- New minor/patch versions are released (can auto-merge if configured) + +Configure in consumer repos: +```yaml +# .github/dependabot.yml +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" +``` diff --git a/action/README.md b/action/README.md index d2ca054da6..fc8a4b9aad 100644 --- a/action/README.md +++ b/action/README.md @@ -26,12 +26,24 @@ This action runs the egg autonomous coding agent within GitHub Actions. It sets ## Quick Start ```yaml -- uses: jwbron/egg@main +- uses: jwbron/egg/action@v0 with: prompt: "Fix the failing tests" anthropic-oauth-token: ${{ secrets.ANTHROPIC_OAUTH_TOKEN }} ``` +### Version Pinning + +For stability, pin to a major version (receives all patch and minor updates): +```yaml +uses: jwbron/egg/action@v0 +``` + +For full reproducibility, pin to an exact version: +```yaml +uses: jwbron/egg/action@v0.1.0 +``` + ## Documentation For design details, inputs, outputs, and implementation notes, see the [GitHub Actions Support ADR](../docs/adr/in-progress/ADR-GitHub-Actions-Support.md). diff --git a/docs/guides/reusable-workflows.md b/docs/guides/reusable-workflows.md index a2b469f690..dde6cee5b3 100644 --- a/docs/guides/reusable-workflows.md +++ b/docs/guides/reusable-workflows.md @@ -6,6 +6,25 @@ This guide explains how to use egg's SDLC workflows in your own repositories. The egg project provides a set of reusable GitHub Actions workflows for AI-powered code review, autofix, conflict resolution, and SDLC pipeline management. These workflows can be called from any repository that has the required secrets configured. +## Version Pinning + +All workflow examples use the `@v0` floating tag, which tracks the latest v0.x.y release. This provides a balance between stability and receiving updates. + +**For stability** (recommended), pin to a major version: +```yaml +uses: jwbron/egg/.github/workflows/reusable-review.yml@v0 +``` + +**For full reproducibility**, pin to an exact version: +```yaml +uses: jwbron/egg/.github/workflows/reusable-review.yml@v0.1.0 +``` + +**For latest development** (not recommended for production): +```yaml +uses: jwbron/egg/.github/workflows/reusable-review.yml@main +``` + ## Available Workflows ### Core Review Workflow @@ -15,12 +34,12 @@ The egg project provides a set of reusable GitHub Actions workflows for AI-power ```yaml jobs: review: - uses: jwbron/egg/.github/workflows/reusable-review.yml@main + uses: jwbron/egg/.github/workflows/reusable-review.yml@v0 with: pr_number: ${{ github.event.pull_request.number }} bot_name: my-bot bot_username: my-bot-username # GitHub username of your bot - # action_ref: jwbron/egg/action@main # Cannot be dynamic; see note below + # action_ref: jwbron/egg/action@v0 # Cannot be dynamic; see note below prompt_script: path/to/build-review-prompt.sh timeout: "10" secrets: @@ -37,7 +56,7 @@ jobs: ```yaml jobs: autofix: - uses: jwbron/egg/.github/workflows/reusable-autofix.yml@main + uses: jwbron/egg/.github/workflows/reusable-autofix.yml@v0 with: pr_number: ${{ github.event.workflow_run.pull_requests[0].number }} failed_workflow: ${{ github.event.workflow_run.name }} @@ -58,7 +77,7 @@ jobs: ```yaml jobs: resolve: - uses: jwbron/egg/.github/workflows/reusable-conflict-resolve.yml@main + uses: jwbron/egg/.github/workflows/reusable-conflict-resolve.yml@v0 with: pr_number: ${{ matrix.pr }} bot_username: my-bot-username @@ -77,7 +96,7 @@ jobs: ```yaml jobs: feedback: - uses: jwbron/egg/.github/workflows/on-review-feedback.yml@main + uses: jwbron/egg/.github/workflows/on-review-feedback.yml@v0 with: pr_number: ${{ github.event.pull_request.number }} bot_username: my-bot-username @@ -97,7 +116,7 @@ jobs: ```yaml jobs: respond: - uses: jwbron/egg/.github/workflows/on-mention.yml@main + uses: jwbron/egg/.github/workflows/on-mention.yml@v0 with: issue_or_pr_number: ${{ github.event.issue.number }} bot_username: my-bot-username @@ -117,7 +136,7 @@ jobs: ```yaml jobs: pipeline: - uses: jwbron/egg/.github/workflows/sdlc-pipeline.yml@main + uses: jwbron/egg/.github/workflows/sdlc-pipeline.yml@v0 with: issue_number: ${{ github.event.issue.number }} bot_username: my-bot-username @@ -141,7 +160,7 @@ The pipeline is triggered by applying the `sdlc:refine` label to an issue. You c | Parameter | Description | Default | |-----------|-------------|---------| | `bot_username` | GitHub username of your bot | `egg` | -| `action_ref` | Reference to egg action (documentation only; see note) | `jwbron/egg/action@main` | +| `action_ref` | Reference to egg action (documentation only; see note) | `jwbron/egg/action@v0` | | `authorized_users` | Comma-separated list of authorized users | `jwbron` | | `branch_prefix` | Prefix for issue branches | `egg` | | `timeout` | Timeout in minutes | varies by workflow | @@ -232,7 +251,7 @@ jobs: permissions: contents: read pull-requests: write - uses: jwbron/egg/.github/workflows/reusable-review.yml@main + uses: jwbron/egg/.github/workflows/reusable-review.yml@v0 with: pr_number: ${{ github.event.pull_request.number }} bot_name: review