From a28e8b3e11abd27b33103646b81fb2bba13cf16c Mon Sep 17 00:00:00 2001 From: Ian Mayo Date: Fri, 28 Nov 2025 21:00:22 +0000 Subject: [PATCH 1/3] feat: implement release automation documentation and workflows --- CLAUDE.md | 2 + .../checklists/requirements.md | 36 ++++++ specs/011-release-automation/plan.md | 67 ++++++++++ specs/011-release-automation/quickstart.md | 56 +++++++++ specs/011-release-automation/research.md | 118 ++++++++++++++++++ specs/011-release-automation/spec.md | 110 ++++++++++++++++ 6 files changed, 389 insertions(+) create mode 100644 specs/011-release-automation/checklists/requirements.md create mode 100644 specs/011-release-automation/plan.md create mode 100644 specs/011-release-automation/quickstart.md create mode 100644 specs/011-release-automation/research.md create mode 100644 specs/011-release-automation/spec.md diff --git a/CLAUDE.md b/CLAUDE.md index 784f89c..9076a65 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -557,6 +557,8 @@ function getStorageKey(release: ReleaseId, serviceId: ServiceId): string { - IndexedDB (primary) - obfuscation at adapter layer; sessionStorage unchanged (009-encrypt-stored-data) - CSS3 + TypeScript 5.x (for JS integration) + Existing DITA template CSS (`f13ldman.css`), Lit 3.x components (010-css-answer-hiding) - N/A (CSS-only feature) (010-css-answer-hiding) +- YAML (GitHub Actions workflows), Bash (scripts) + GitHub Actions (actions/checkout, actions/setup-node, softprops/action-gh-release) (011-release-automation) +- N/A (CI/CD infrastructure only) (011-release-automation) ## Recent Changes - 001-security-refactor: Added TypeScript 5.x / JavaScript ES2020+ + Lit 3.0 (Web Components), Vite 5.x (build), Vitest (testing) diff --git a/specs/011-release-automation/checklists/requirements.md b/specs/011-release-automation/checklists/requirements.md new file mode 100644 index 0000000..d935785 --- /dev/null +++ b/specs/011-release-automation/checklists/requirements.md @@ -0,0 +1,36 @@ +# Specification Quality Checklist: Release Automation + +**Purpose**: Validate specification completeness and quality before proceeding to planning +**Created**: 2025-11-28 +**Feature**: [spec.md](../spec.md) + +## Content Quality + +- [x] No implementation details (languages, frameworks, APIs) +- [x] Focused on user value and business needs +- [x] Written for non-technical stakeholders +- [x] All mandatory sections completed + +## Requirement Completeness + +- [x] No [NEEDS CLARIFICATION] markers remain +- [x] Requirements are testable and unambiguous +- [x] Success criteria are measurable +- [x] Success criteria are technology-agnostic (no implementation details) +- [x] All acceptance scenarios are defined +- [x] Edge cases are identified +- [x] Scope is clearly bounded +- [x] Dependencies and assumptions identified + +## Feature Readiness + +- [x] All functional requirements have clear acceptance criteria +- [x] User scenarios cover primary flows +- [x] Feature meets measurable outcomes defined in Success Criteria +- [x] No implementation details leak into specification + +## Notes + +- All items pass validation +- Spec is ready for `/speckit.clarify` or `/speckit.plan` +- Conventional commits assumption documented - may need user confirmation during planning diff --git a/specs/011-release-automation/plan.md b/specs/011-release-automation/plan.md new file mode 100644 index 0000000..90c7c72 --- /dev/null +++ b/specs/011-release-automation/plan.md @@ -0,0 +1,67 @@ +# Implementation Plan: Release Automation + +**Branch**: `011-release-automation` | **Date**: 2025-11-28 | **Spec**: [spec.md](./spec.md) +**Input**: Feature specification from `/specs/011-release-automation/spec.md` + +## Summary + +Establish CI/CD automation for semantic versioning releases via GitHub Actions. Manual workflow trigger creates GitHub Releases with version tags, release notes from commit history, and attached bundle artifacts. Version bumping inferred from conventional commit prefixes (feat→minor, fix→patch) with manual override option. + +## Technical Context + +**Language/Version**: YAML (GitHub Actions workflows), Bash (scripts) +**Primary Dependencies**: GitHub Actions (actions/checkout, actions/setup-node, softprops/action-gh-release) +**Storage**: N/A (CI/CD infrastructure only) +**Testing**: Manual workflow execution, workflow syntax validation +**Target Platform**: GitHub Actions runners (ubuntu-latest) +**Project Type**: Single project with existing CI workflows +**Performance Goals**: Release workflow completes in <5 minutes +**Constraints**: Must run all CI checks before release; no orphaned tags on failure + +## Constitution Check + +*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* + +- [x] **Offline-First**: N/A - CI/CD infrastructure, not runtime code. Does not affect offline operation. +- [x] **Progressive Enhancement**: N/A - No changes to runtime behavior or DITA enhancement. +- [x] **Test-Driven Development**: Workflow validated via dry-run testing before merge. +- [x] **Phase-Gated Delivery**: Clear exit criteria: workflow runs, release created with artifacts. +- [x] **Performance Constraints**: N/A - Does not affect bundle size or runtime performance. +- [x] **Data Isolation**: N/A - No user data involved. +- [x] **Zero Configuration**: N/A - Deployment infrastructure, not runtime script. + +**All gates pass** - This feature is purely CI/CD infrastructure with no impact on the constitution's runtime constraints. + +## Project Structure + +### Documentation (this feature) + +```text +specs/011-release-automation/ +├── plan.md # This file +├── research.md # Phase 0 output +├── data-model.md # N/A - no data entities +├── quickstart.md # Release instructions +├── contracts/ # N/A - no API contracts +└── tasks.md # Phase 2 output +``` + +### Source Code (repository root) + +```text +.github/workflows/ +├── ci.yml # Existing CI workflow (lint, test, build) +├── pages.yml # Existing GitHub Pages deployment +├── pr-preview.yml # Existing PR preview deployment +├── pr-preview-comment.yml +└── release.yml # NEW: Release automation workflow + +docs/ +└── RELEASE.md # NEW: Release process documentation +``` + +**Structure Decision**: Single new workflow file plus documentation. Follows existing GitHub Actions patterns established in ci.yml. + +## Complexity Tracking + +No constitution violations. Feature is infrastructure-only. diff --git a/specs/011-release-automation/quickstart.md b/specs/011-release-automation/quickstart.md new file mode 100644 index 0000000..45adc7b --- /dev/null +++ b/specs/011-release-automation/quickstart.md @@ -0,0 +1,56 @@ +# Quickstart: Release Automation + +## Creating a Release + +### Via GitHub UI (Recommended) + +1. Go to **Actions** → **Release** workflow +2. Click **Run workflow** +3. Optional: Enter specific version (e.g., `1.2.0`) or leave blank for auto-detect +4. Click **Run workflow** button +5. Wait for workflow to complete (~3-5 minutes) +6. New release appears at **Releases** with attached bundle + +### Via GitHub CLI + +```bash +# Auto-detect version from commits +gh workflow run release.yml + +# Specify version explicitly +gh workflow run release.yml -f version=1.2.0 +``` + +## Version Bumping Rules + +| Commit Type | Version Bump | Example | +|-------------|--------------|---------| +| `feat:` | Minor (0.X.0) | `feat: add new quiz type` | +| `fix:` | Patch (0.0.X) | `fix: correct score calculation` | +| `BREAKING CHANGE:` | Major (X.0.0) | `feat!: change API` | +| Other | Patch | `docs: update readme` | + +## What Gets Released + +- **sonar-quiz.iife.js** - Production bundle +- **sonar-quiz.iife.js.map** - Source map +- **Source code** - Auto-generated zip/tar.gz + +## Workflow Diagram + +``` +trigger → lint → test → build → version-bump → tag → release + ↓ + artifact upload +``` + +## Troubleshooting + +### "No commits since last release" +Release is blocked. Make some changes first. + +### Workflow fails mid-way +No partial release created. Fix the issue and re-run. + +### Want to re-release same version +Delete the tag first: `git push --delete origin v1.2.0` diff --git a/specs/011-release-automation/research.md b/specs/011-release-automation/research.md new file mode 100644 index 0000000..a4ca64c --- /dev/null +++ b/specs/011-release-automation/research.md @@ -0,0 +1,118 @@ +# Research: Release Automation + +**Feature**: 011-release-automation +**Date**: 2025-11-28 + +## Research Questions + +### 1. GitHub Actions Release Strategy + +**Decision**: Use `softprops/action-gh-release` for GitHub Release creation + +**Rationale**: +- Most popular and well-maintained action for GitHub releases (17k+ stars) +- Supports automatic changelog generation from git commits +- Handles asset uploads (bundle artifacts) +- Provides tag creation and version management +- Alternative: manual `gh release create` commands would work but require more scripting + +**Alternatives Considered**: +- `ncipollo/release-action`: Similar features, slightly less popular +- Manual `gh` CLI: More flexible but requires more maintenance +- `release-drafter/release-drafter`: Better for draft-based workflows, overkill here + +### 2. Version Inference from Commits + +**Decision**: Use simple shell script to parse conventional commits + +**Rationale**: +- Project already uses conventional commit format (verified: `feat:`, `fix:` prefixes in git log) +- Shell-based parsing is lightweight and doesn't add npm dependencies +- Logic: Any `feat:` since last tag → minor bump; only `fix:` → patch; `BREAKING CHANGE:` or `!:` → major +- Falls back to patch for unrecognized prefixes + +**Alternatives Considered**: +- `conventional-changelog/standard-version`: Full npm package, overkill for our needs +- `semantic-release`: Too complex, adds many dependencies +- `release-please`: Google's solution, good but heavyweight + +### 3. Workflow Trigger Mechanism + +**Decision**: Use `workflow_dispatch` with optional version input + +**Rationale**: +- Manual trigger gives control over release timing +- Input field allows version override when automatic inference isn't desired +- No accidental releases from push events +- Matches existing workflow patterns in project + +**Example**: +```yaml +on: + workflow_dispatch: + inputs: + version: + description: 'Version (leave blank for auto-detect from commits)' + required: false + type: string +``` + +### 4. CI Check Enforcement + +**Decision**: Run full CI suite within release workflow before creating release + +**Rationale**: +- Ensures all tests pass before any release artifacts are created +- Prevents partial releases if tests fail +- Uses same jobs as ci.yml (lint, test, build) as reusable steps +- Only proceeds to release creation if all checks pass + +**Implementation**: +- Release job has `needs: [lint, test, build]` dependency +- Build job uploads artifacts; release job downloads and attaches them + +### 5. Artifact Handling + +**Decision**: Build bundle in workflow, attach as release asset + +**Rationale**: +- Uses existing `npm run build` which produces `dist/sonar-quiz.iife.js` +- Bundle is the primary deliverable for integrators +- Source code archives are automatically created by GitHub + +**Assets to attach**: +- `sonar-quiz.iife.js` (main bundle) +- `sonar-quiz.iife.js.map` (source map for debugging) + +### 6. Package.json Version Update + +**Decision**: Update package.json version and commit during release + +**Rationale**: +- Keeps package.json in sync with git tags +- Standard practice for JS projects +- Commit message: `chore(release): v{version}` +- Pushed to main branch after successful release + +**Workflow sequence**: +1. Calculate new version +2. Update package.json +3. Commit version bump +4. Create git tag +5. Build with new version +6. Create GitHub Release with assets +7. Push commit and tag + +### 7. Release Notes Generation + +**Decision**: Auto-generate from commits using `softprops/action-gh-release` with `generate_release_notes: true` + +**Rationale**: +- GitHub's built-in release notes are sufficient +- Groups commits by type automatically +- No need for CHANGELOG.md maintenance +- Can be customized via `.github/release.yml` if needed later + +## No Further Clarifications Needed + +All technical decisions resolved. Ready for Phase 1 artifacts. diff --git a/specs/011-release-automation/spec.md b/specs/011-release-automation/spec.md new file mode 100644 index 0000000..39422c0 --- /dev/null +++ b/specs/011-release-automation/spec.md @@ -0,0 +1,110 @@ +# Feature Specification: Release Automation + +**Feature Branch**: `011-release-automation` +**Created**: 2025-11-28 +**Status**: Draft +**Input**: GitHub Issue #88 - Release policy / mechanism + +## Overview + +Establish a formal release process with CI/CD automation for consistent semantic versioning (vX.Y.Z) releases. Modeled after sister project (GramFrame) release documentation and workflows. + +## User Scenarios & Testing *(mandatory)* + +### User Story 1 - Trigger a New Release (Priority: P1) + +A maintainer wants to create a new versioned release of the project with minimal manual steps. They trigger the release process and the system handles version bumping, changelog generation, GitHub release creation, and artifact publishing. + +**Why this priority**: Core value of the feature - automated releases reduce human error and friction. + +**Independent Test**: Can be tested by triggering a release workflow manually from GitHub Actions and verifying a new GitHub Release is created with correct version and artifacts. + +**Acceptance Scenarios**: + +1. **Given** the main branch has unreleased commits, **When** a maintainer triggers the release workflow, **Then** a new GitHub Release is created with incremented version +2. **Given** a release is triggered, **When** the workflow completes, **Then** the release includes the built bundle artifact (sonar-quiz.iife.js) +3. **Given** a release is triggered, **When** the workflow completes, **Then** the release notes summarize changes since the last release + +--- + +### User Story 2 - View Release Documentation (Priority: P2) + +A contributor or maintainer wants to understand the release process, versioning strategy, and how to trigger releases. They can find clear documentation that explains the policy. + +**Why this priority**: Documentation enables self-service and reduces onboarding friction. + +**Independent Test**: Can be tested by reviewing that RELEASE.md exists and contains complete instructions. + +**Acceptance Scenarios**: + +1. **Given** a new contributor, **When** they read RELEASE.md, **Then** they understand how versioning works +2. **Given** a maintainer, **When** they read RELEASE.md, **Then** they know how to trigger a release + +--- + +### User Story 3 - Automatic Version Bumping (Priority: P3) + +The system automatically determines the appropriate version bump (major/minor/patch) based on conventional commit messages or allows explicit specification. + +**Why this priority**: Semantic versioning consistency is valuable but manual override works as fallback. + +**Independent Test**: Can be tested by making commits with conventional prefixes and verifying version inference. + +**Acceptance Scenarios**: + +1. **Given** commits with `feat:` prefix since last release, **When** release is triggered, **Then** minor version is bumped +2. **Given** commits with `fix:` prefix only, **When** release is triggered, **Then** patch version is bumped +3. **Given** explicit version override, **When** maintainer specifies version, **Then** that exact version is used + +--- + +### Edge Cases + +- What happens when no commits exist since last release? (Release is blocked with informative message) +- What happens when the workflow fails mid-release? (Partial artifacts are cleaned up, no orphaned tags) +- What happens when package.json version conflicts with git tags? (Warning issued, tag version takes precedence) + +## Requirements *(mandatory)* + +### Functional Requirements + +- **FR-001**: System MUST provide a GitHub Actions workflow that creates GitHub Releases +- **FR-002**: System MUST generate release artifacts including the production bundle (dist/sonar-quiz.iife.js) +- **FR-003**: System MUST tag releases with semantic version format (vX.Y.Z) +- **FR-004**: System MUST update package.json version during release +- **FR-005**: System MUST generate release notes from commit history +- **FR-006**: System MUST allow manual trigger of release workflow with optional version override +- **FR-007**: System MUST validate that all CI checks pass before creating a release +- **FR-008**: System MUST document the release process in RELEASE.md +- **FR-009**: Releases MUST include source code archives (zip, tar.gz - GitHub default) +- **FR-010**: System MUST attach the built bundle as a downloadable release asset + +### Key Entities + +- **Release**: A versioned snapshot with version tag, changelog, and artifacts +- **Version**: Semantic version (major.minor.patch) tracked in package.json and git tags +- **Release Asset**: Built bundle file attached to GitHub Release for download + +## Success Criteria *(mandatory)* + +### Measurable Outcomes + +- **SC-001**: A new release can be created within 5 minutes of triggering the workflow +- **SC-002**: 100% of releases include the production bundle artifact +- **SC-003**: Release documentation is comprehensive enough for any maintainer to trigger a release without external guidance +- **SC-004**: Zero manual file editing required for standard releases (version bump is automated) +- **SC-005**: All releases pass CI validation before publishing + +## Assumptions + +- Conventional commits format is already used or will be adopted for commit messages +- GitHub Actions is the CI/CD platform (already in use for PR previews and pages deployment) +- The existing npm build process produces valid production bundles +- Maintainers have appropriate GitHub permissions to trigger workflows and create releases + +## Out of Scope + +- NPM package publishing (project is not an npm package for distribution) +- CDN deployment (offline-first architecture) +- Automatic release scheduling (releases are manually triggered) +- Pre-release/beta versioning (can be added later if needed) From 91e2b8534eba23bf293cc77d834850f8a2890d9b Mon Sep 17 00:00:00 2001 From: Ian Mayo Date: Fri, 28 Nov 2025 21:00:35 +0000 Subject: [PATCH 2/3] feat: implement tag-triggered release automation with updated documentation and workflows --- specs/011-release-automation/plan.md | 10 +- specs/011-release-automation/quickstart.md | 81 ++++++---- specs/011-release-automation/research.md | 74 ++++----- specs/011-release-automation/spec.md | 73 ++++----- specs/011-release-automation/tasks.md | 165 +++++++++++++++++++++ 5 files changed, 303 insertions(+), 100 deletions(-) create mode 100644 specs/011-release-automation/tasks.md diff --git a/specs/011-release-automation/plan.md b/specs/011-release-automation/plan.md index 90c7c72..51d065c 100644 --- a/specs/011-release-automation/plan.md +++ b/specs/011-release-automation/plan.md @@ -5,18 +5,18 @@ ## Summary -Establish CI/CD automation for semantic versioning releases via GitHub Actions. Manual workflow trigger creates GitHub Releases with version tags, release notes from commit history, and attached bundle artifacts. Version bumping inferred from conventional commit prefixes (feat→minor, fix→patch) with manual override option. +Establish CI/CD automation for semantic versioning releases via GitHub Actions. Releases are triggered by pushing a `vX.Y.Z` tag to the main branch. The workflow validates CI checks, builds the bundle, updates package.json to match the tag version, and creates a GitHub Release with artifacts attached. ## Technical Context **Language/Version**: YAML (GitHub Actions workflows), Bash (scripts) **Primary Dependencies**: GitHub Actions (actions/checkout, actions/setup-node, softprops/action-gh-release) **Storage**: N/A (CI/CD infrastructure only) -**Testing**: Manual workflow execution, workflow syntax validation +**Testing**: Tag push to trigger workflow, verify release creation **Target Platform**: GitHub Actions runners (ubuntu-latest) **Project Type**: Single project with existing CI workflows **Performance Goals**: Release workflow completes in <5 minutes -**Constraints**: Must run all CI checks before release; no orphaned tags on failure +**Constraints**: Must run all CI checks before release; tag is source of truth for version ## Constitution Check @@ -24,7 +24,7 @@ Establish CI/CD automation for semantic versioning releases via GitHub Actions. - [x] **Offline-First**: N/A - CI/CD infrastructure, not runtime code. Does not affect offline operation. - [x] **Progressive Enhancement**: N/A - No changes to runtime behavior or DITA enhancement. -- [x] **Test-Driven Development**: Workflow validated via dry-run testing before merge. +- [x] **Test-Driven Development**: Workflow validated via tag push testing before merge. - [x] **Phase-Gated Delivery**: Clear exit criteria: workflow runs, release created with artifacts. - [x] **Performance Constraints**: N/A - Does not affect bundle size or runtime performance. - [x] **Data Isolation**: N/A - No user data involved. @@ -54,7 +54,7 @@ specs/011-release-automation/ ├── pages.yml # Existing GitHub Pages deployment ├── pr-preview.yml # Existing PR preview deployment ├── pr-preview-comment.yml -└── release.yml # NEW: Release automation workflow +└── release.yml # NEW: Release automation workflow (tag-triggered) docs/ └── RELEASE.md # NEW: Release process documentation diff --git a/specs/011-release-automation/quickstart.md b/specs/011-release-automation/quickstart.md index 45adc7b..1e3d499 100644 --- a/specs/011-release-automation/quickstart.md +++ b/specs/011-release-automation/quickstart.md @@ -2,33 +2,40 @@ ## Creating a Release -### Via GitHub UI (Recommended) +### Via Git Tag (Recommended) -1. Go to **Actions** → **Release** workflow -2. Click **Run workflow** -3. Optional: Enter specific version (e.g., `1.2.0`) or leave blank for auto-detect -4. Click **Run workflow** button -5. Wait for workflow to complete (~3-5 minutes) -6. New release appears at **Releases** with attached bundle +```bash +# 1. Ensure you're on main branch with latest changes +git checkout main +git pull origin main + +# 2. Create and push a version tag +git tag v0.1.5 +git push origin v0.1.5 + +# 3. Watch the release workflow +# GitHub Actions automatically triggers on tag push +# Release appears at Releases page in ~3-5 minutes +``` ### Via GitHub CLI ```bash -# Auto-detect version from commits -gh workflow run release.yml - -# Specify version explicitly -gh workflow run release.yml -f version=1.2.0 +# Create and push tag in one command +gh release create v0.1.5 --generate-notes ``` -## Version Bumping Rules +**Note**: The workflow triggers automatically when you push a `vX.Y.Z` tag. No manual workflow dispatch needed. -| Commit Type | Version Bump | Example | -|-------------|--------------|---------| -| `feat:` | Minor (0.X.0) | `feat: add new quiz type` | -| `fix:` | Patch (0.0.X) | `fix: correct score calculation` | -| `BREAKING CHANGE:` | Major (X.0.0) | `feat!: change API` | -| Other | Patch | `docs: update readme` | +## Version Format + +Tags MUST follow semantic versioning format: `vX.Y.Z` + +| Valid | Invalid | +|-------|---------| +| `v0.1.5` | `0.1.5` (missing 'v') | +| `v1.0.0` | `v1.0` (missing patch) | +| `v10.20.30` | `release-1.0.0` (wrong prefix) | ## What Gets Released @@ -39,18 +46,42 @@ gh workflow run release.yml -f version=1.2.0 ## Workflow Diagram ``` -trigger → lint → test → build → version-bump → tag → release +tag push → lint → test → build → release ↓ artifact upload + ↓ + package.json sync ``` ## Troubleshooting -### "No commits since last release" -Release is blocked. Make some changes first. +### Tag pushed but no release created +- Check tag format matches `vX.Y.Z` pattern +- Verify tag was pushed to origin: `git ls-remote --tags origin` +- Check Actions tab for workflow failures -### Workflow fails mid-way -No partial release created. Fix the issue and re-run. +### CI checks failing +Release won't be created if lint, tests, or build fail. Fix the issues on main first, delete the tag, then re-tag. + +```bash +# Delete remote tag +git push --delete origin v0.1.5 + +# Delete local tag +git tag -d v0.1.5 + +# Fix issues, then re-tag +git tag v0.1.5 +git push origin v0.1.5 +``` ### Want to re-release same version -Delete the tag first: `git push --delete origin v1.2.0` +Delete the existing release and tag first: + +```bash +# Delete release via CLI +gh release delete v0.1.5 + +# Delete remote tag +git push --delete origin v0.1.5 +``` diff --git a/specs/011-release-automation/research.md b/specs/011-release-automation/research.md index a4ca64c..5ab1aaa 100644 --- a/specs/011-release-automation/research.md +++ b/specs/011-release-automation/research.md @@ -13,7 +13,7 @@ - Most popular and well-maintained action for GitHub releases (17k+ stars) - Supports automatic changelog generation from git commits - Handles asset uploads (bundle artifacts) -- Provides tag creation and version management +- Works seamlessly with tag-triggered workflows - Alternative: manual `gh release create` commands would work but require more scripting **Alternatives Considered**: @@ -21,40 +21,44 @@ - Manual `gh` CLI: More flexible but requires more maintenance - `release-drafter/release-drafter`: Better for draft-based workflows, overkill here -### 2. Version Inference from Commits +### 2. Workflow Trigger Mechanism -**Decision**: Use simple shell script to parse conventional commits +**Decision**: Use tag push trigger with pattern matching for `v*` tags **Rationale**: -- Project already uses conventional commit format (verified: `feat:`, `fix:` prefixes in git log) -- Shell-based parsing is lightweight and doesn't add npm dependencies -- Logic: Any `feat:` since last tag → minor bump; only `fix:` → patch; `BREAKING CHANGE:` or `!:` → major -- Falls back to patch for unrecognized prefixes +- User preference: pushing a tag like `v0.1.5` triggers the release +- Simple and intuitive - version is explicit in the tag +- No need for version inference from commits +- Matches common open-source project patterns -**Alternatives Considered**: -- `conventional-changelog/standard-version`: Full npm package, overkill for our needs -- `semantic-release`: Too complex, adds many dependencies -- `release-please`: Google's solution, good but heavyweight +**Implementation**: +```yaml +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' +``` + +This pattern matches: +- `v0.1.5` ✓ +- `v1.0.0` ✓ +- `v10.20.30` ✓ +- `v1.0` ✗ (invalid - must have 3 parts) +- `release-1.0.0` ✗ (must start with 'v') -### 3. Workflow Trigger Mechanism +### 3. Version Extraction from Tag -**Decision**: Use `workflow_dispatch` with optional version input +**Decision**: Extract version from `GITHUB_REF_NAME` environment variable **Rationale**: -- Manual trigger gives control over release timing -- Input field allows version override when automatic inference isn't desired -- No accidental releases from push events -- Matches existing workflow patterns in project +- GitHub Actions provides the tag name directly +- Strip leading 'v' for package.json update: `${GITHUB_REF_NAME#v}` +- No complex parsing needed **Example**: -```yaml -on: - workflow_dispatch: - inputs: - version: - description: 'Version (leave blank for auto-detect from commits)' - required: false - type: string +```bash +# Tag: v0.1.5 +VERSION=${GITHUB_REF_NAME#v} # Results in: 0.1.5 ``` ### 4. CI Check Enforcement @@ -63,7 +67,7 @@ on: **Rationale**: - Ensures all tests pass before any release artifacts are created -- Prevents partial releases if tests fail +- Prevents invalid releases if tests fail - Uses same jobs as ci.yml (lint, test, build) as reusable steps - Only proceeds to release creation if all checks pass @@ -86,22 +90,20 @@ on: ### 6. Package.json Version Update -**Decision**: Update package.json version and commit during release +**Decision**: Update package.json to match tag version and commit back to main **Rationale**: -- Keeps package.json in sync with git tags +- Keeps package.json in sync with git tags (tag is source of truth) - Standard practice for JS projects - Commit message: `chore(release): v{version}` - Pushed to main branch after successful release **Workflow sequence**: -1. Calculate new version -2. Update package.json -3. Commit version bump -4. Create git tag -5. Build with new version -6. Create GitHub Release with assets -7. Push commit and tag +1. Tag triggers workflow +2. Run CI checks (lint, test, build) +3. Update package.json version to match tag +4. Commit version update to main +5. Create GitHub Release with assets ### 7. Release Notes Generation @@ -115,4 +117,4 @@ on: ## No Further Clarifications Needed -All technical decisions resolved. Ready for Phase 1 artifacts. +All technical decisions resolved. Ready for implementation. diff --git a/specs/011-release-automation/spec.md b/specs/011-release-automation/spec.md index 39422c0..ed62881 100644 --- a/specs/011-release-automation/spec.md +++ b/specs/011-release-automation/spec.md @@ -7,29 +7,35 @@ ## Overview -Establish a formal release process with CI/CD automation for consistent semantic versioning (vX.Y.Z) releases. Modeled after sister project (GramFrame) release documentation and workflows. +Establish a formal release process with CI/CD automation for consistent semantic versioning (vX.Y.Z) releases. Releases are triggered by pushing a version tag (e.g., `v0.1.5`) to the main branch. Modeled after sister project (GramFrame) release documentation and workflows. + +## Clarifications + +### Session 2025-11-28 + +- Q: How should releases be triggered? → A: Tag-triggered - pushing a `vX.Y.Z` tag to main branch triggers the release workflow ## User Scenarios & Testing *(mandatory)* ### User Story 1 - Trigger a New Release (Priority: P1) -A maintainer wants to create a new versioned release of the project with minimal manual steps. They trigger the release process and the system handles version bumping, changelog generation, GitHub release creation, and artifact publishing. +A maintainer wants to create a new versioned release of the project. They push a version tag (e.g., `v0.1.5`) to the main branch, and the system automatically builds, validates, and publishes a GitHub Release with artifacts. **Why this priority**: Core value of the feature - automated releases reduce human error and friction. -**Independent Test**: Can be tested by triggering a release workflow manually from GitHub Actions and verifying a new GitHub Release is created with correct version and artifacts. +**Independent Test**: Can be tested by pushing a `vX.Y.Z` tag to main and verifying a new GitHub Release is created with correct version and artifacts. **Acceptance Scenarios**: -1. **Given** the main branch has unreleased commits, **When** a maintainer triggers the release workflow, **Then** a new GitHub Release is created with incremented version -2. **Given** a release is triggered, **When** the workflow completes, **Then** the release includes the built bundle artifact (sonar-quiz.iife.js) -3. **Given** a release is triggered, **When** the workflow completes, **Then** the release notes summarize changes since the last release +1. **Given** the main branch has commits, **When** a maintainer pushes a tag `v0.1.5`, **Then** a new GitHub Release `v0.1.5` is created +2. **Given** a release is triggered by tag, **When** the workflow completes, **Then** the release includes the built bundle artifact (sonar-quiz.iife.js) +3. **Given** a release is triggered by tag, **When** the workflow completes, **Then** the release notes summarize changes since the previous tag --- ### User Story 2 - View Release Documentation (Priority: P2) -A contributor or maintainer wants to understand the release process, versioning strategy, and how to trigger releases. They can find clear documentation that explains the policy. +A contributor or maintainer wants to understand the release process, versioning strategy, and how to create releases. They can find clear documentation that explains the policy. **Why this priority**: Documentation enables self-service and reduces onboarding friction. @@ -38,73 +44,72 @@ A contributor or maintainer wants to understand the release process, versioning **Acceptance Scenarios**: 1. **Given** a new contributor, **When** they read RELEASE.md, **Then** they understand how versioning works -2. **Given** a maintainer, **When** they read RELEASE.md, **Then** they know how to trigger a release +2. **Given** a maintainer, **When** they read RELEASE.md, **Then** they know how to create a release via tagging --- -### User Story 3 - Automatic Version Bumping (Priority: P3) +### User Story 3 - Package.json Version Sync (Priority: P3) -The system automatically determines the appropriate version bump (major/minor/patch) based on conventional commit messages or allows explicit specification. +The system keeps package.json version in sync with the git tag used for the release. -**Why this priority**: Semantic versioning consistency is valuable but manual override works as fallback. +**Why this priority**: Version consistency is important but the git tag is the source of truth. -**Independent Test**: Can be tested by making commits with conventional prefixes and verifying version inference. +**Independent Test**: Can be tested by checking that package.json version matches the release tag after workflow completes. **Acceptance Scenarios**: -1. **Given** commits with `feat:` prefix since last release, **When** release is triggered, **Then** minor version is bumped -2. **Given** commits with `fix:` prefix only, **When** release is triggered, **Then** patch version is bumped -3. **Given** explicit version override, **When** maintainer specifies version, **Then** that exact version is used +1. **Given** a tag `v0.1.5` is pushed, **When** release workflow runs, **Then** package.json version is updated to `0.1.5` +2. **Given** package.json has version `0.1.0`, **When** tag `v0.2.0` triggers release, **Then** package.json is updated and committed --- ### Edge Cases -- What happens when no commits exist since last release? (Release is blocked with informative message) -- What happens when the workflow fails mid-release? (Partial artifacts are cleaned up, no orphaned tags) -- What happens when package.json version conflicts with git tags? (Warning issued, tag version takes precedence) +- What happens when tag format is invalid (not vX.Y.Z)? (Workflow ignores non-matching tags) +- What happens when CI checks fail after tag push? (Release is not created, tag remains, error reported) +- What happens when package.json update fails? (Release continues, warning issued - tag is source of truth) ## Requirements *(mandatory)* ### Functional Requirements -- **FR-001**: System MUST provide a GitHub Actions workflow that creates GitHub Releases +- **FR-001**: System MUST provide a GitHub Actions workflow triggered by `vX.Y.Z` tags on main branch - **FR-002**: System MUST generate release artifacts including the production bundle (dist/sonar-quiz.iife.js) -- **FR-003**: System MUST tag releases with semantic version format (vX.Y.Z) -- **FR-004**: System MUST update package.json version during release -- **FR-005**: System MUST generate release notes from commit history -- **FR-006**: System MUST allow manual trigger of release workflow with optional version override -- **FR-007**: System MUST validate that all CI checks pass before creating a release -- **FR-008**: System MUST document the release process in RELEASE.md -- **FR-009**: Releases MUST include source code archives (zip, tar.gz - GitHub default) -- **FR-010**: System MUST attach the built bundle as a downloadable release asset +- **FR-003**: System MUST create GitHub Release with the same version as the pushed tag +- **FR-004**: System MUST update package.json version to match the tag version +- **FR-005**: System MUST generate release notes from commit history since previous tag +- **FR-006**: System MUST validate that all CI checks pass before creating a release +- **FR-007**: System MUST document the release process in RELEASE.md +- **FR-008**: Releases MUST include source code archives (zip, tar.gz - GitHub default) +- **FR-009**: System MUST attach the built bundle as a downloadable release asset +- **FR-010**: System MUST ignore tags that don't match the `vX.Y.Z` pattern ### Key Entities - **Release**: A versioned snapshot with version tag, changelog, and artifacts -- **Version**: Semantic version (major.minor.patch) tracked in package.json and git tags +- **Version Tag**: Git tag in format `vX.Y.Z` that triggers the release workflow - **Release Asset**: Built bundle file attached to GitHub Release for download ## Success Criteria *(mandatory)* ### Measurable Outcomes -- **SC-001**: A new release can be created within 5 minutes of triggering the workflow +- **SC-001**: A new release is created within 5 minutes of pushing a valid version tag - **SC-002**: 100% of releases include the production bundle artifact -- **SC-003**: Release documentation is comprehensive enough for any maintainer to trigger a release without external guidance -- **SC-004**: Zero manual file editing required for standard releases (version bump is automated) +- **SC-003**: Release documentation is comprehensive enough for any maintainer to create a release without external guidance +- **SC-004**: Package.json version matches git tag version after release - **SC-005**: All releases pass CI validation before publishing ## Assumptions -- Conventional commits format is already used or will be adopted for commit messages +- Maintainers will push tags in valid `vX.Y.Z` format - GitHub Actions is the CI/CD platform (already in use for PR previews and pages deployment) - The existing npm build process produces valid production bundles -- Maintainers have appropriate GitHub permissions to trigger workflows and create releases +- Maintainers have appropriate GitHub permissions to push tags and create releases ## Out of Scope - NPM package publishing (project is not an npm package for distribution) - CDN deployment (offline-first architecture) -- Automatic release scheduling (releases are manually triggered) +- Automatic version inference from commits (version is explicit in tag) - Pre-release/beta versioning (can be added later if needed) diff --git a/specs/011-release-automation/tasks.md b/specs/011-release-automation/tasks.md new file mode 100644 index 0000000..c15402c --- /dev/null +++ b/specs/011-release-automation/tasks.md @@ -0,0 +1,165 @@ +# Tasks: Release Automation + +**Input**: Design documents from `/specs/011-release-automation/` +**Prerequisites**: plan.md (required), spec.md (required), research.md + +**Tests**: Not applicable - CI/CD infrastructure is validated through tag push and release verification + +**Organization**: Tasks grouped by user story for independent implementation + +## Format: `[ID] [P?] [Story] Description` + +- **[P]**: Can run in parallel (different files, no dependencies) +- **[Story]**: Which user story this task belongs to (US1, US2, US3) +- Include exact file paths in descriptions + +--- + +## Phase 1: Setup (Shared Infrastructure) + +**Purpose**: No setup required - project already has GitHub Actions infrastructure + +- [ ] T001 Verify existing CI workflow structure in .github/workflows/ci.yml + +**Checkpoint**: Existing infrastructure confirmed + +--- + +## Phase 2: Foundational (Blocking Prerequisites) + +**Purpose**: No foundational work needed - this feature adds new workflow, doesn't modify existing + +**⚠️ Note**: This feature is additive - no blocking prerequisites + +**Checkpoint**: Ready to begin user stories + +--- + +## Phase 3: User Story 1 - Trigger a New Release (Priority: P1) 🎯 MVP + +**Goal**: Pushing a `vX.Y.Z` tag to main triggers workflow that creates GitHub Release with bundle artifacts + +**Independent Test**: Push tag `v0.1.5` to main, verify GitHub Release created with correct version and attached sonar-quiz.iife.js + +### Implementation for User Story 1 + +- [ ] T002 [US1] Create release workflow file with tag push trigger (v[0-9]+.[0-9]+.[0-9]+) in .github/workflows/release.yml +- [ ] T003 [US1] Add CI validation jobs (lint, test, build) reusing patterns from ci.yml in .github/workflows/release.yml +- [ ] T004 [US1] Add version extraction step from GITHUB_REF_NAME in .github/workflows/release.yml +- [ ] T005 [US1] Add GitHub Release creation using softprops/action-gh-release in .github/workflows/release.yml +- [ ] T006 [US1] Configure release notes auto-generation from commits in .github/workflows/release.yml +- [ ] T007 [US1] Configure artifact upload (sonar-quiz.iife.js, source map) as release assets in .github/workflows/release.yml +- [ ] T008 [US1] Add permissions block for contents:write in .github/workflows/release.yml + +**Checkpoint**: Release workflow functional - tag push creates release with artifacts + +--- + +## Phase 4: User Story 2 - View Release Documentation (Priority: P2) + +**Goal**: Contributors can find clear documentation explaining release process via tagging + +**Independent Test**: Read docs/RELEASE.md and verify it contains complete tagging instructions + +### Implementation for User Story 2 + +- [ ] T009 [P] [US2] Create RELEASE.md with overview section explaining semantic versioning in docs/RELEASE.md +- [ ] T010 [P] [US2] Add "How to Create a Release" section with git tag commands in docs/RELEASE.md +- [ ] T011 [US2] Add version format requirements (vX.Y.Z pattern) in docs/RELEASE.md +- [ ] T012 [US2] Add troubleshooting section for common issues in docs/RELEASE.md + +**Checkpoint**: Documentation complete - any maintainer can self-service release process + +--- + +## Phase 5: User Story 3 - Package.json Version Sync (Priority: P3) + +**Goal**: Package.json version is updated to match the git tag after release + +**Independent Test**: Push tag v0.2.0, verify package.json version updated to 0.2.0 on main branch + +### Implementation for User Story 3 + +- [ ] T013 [US3] Add package.json version update step extracting version from tag in .github/workflows/release.yml +- [ ] T014 [US3] Add git commit for version update with message "chore(release): vX.Y.Z" in .github/workflows/release.yml +- [ ] T015 [US3] Add git push to main branch for version commit in .github/workflows/release.yml +- [ ] T016 [US3] Handle edge case: skip version commit if package.json already matches tag in .github/workflows/release.yml + +**Checkpoint**: Package.json stays in sync with release tags + +--- + +## Phase 6: Polish & Cross-Cutting Concerns + +**Purpose**: Edge cases and final validation + +- [ ] T017 Update README.md with release process reference and link to docs/RELEASE.md +- [ ] T018 Test by pushing test tag on feature branch to validate workflow syntax before merge + +--- + +## Dependencies & Execution Order + +### Phase Dependencies + +- **Setup (Phase 1)**: Verification only - no changes +- **Foundational (Phase 2)**: N/A - additive feature +- **User Story 1 (Phase 3)**: Core workflow - MVP +- **User Story 2 (Phase 4)**: Documentation - independent of US1 +- **User Story 3 (Phase 5)**: Enhances US1 - depends on workflow existing +- **Polish (Phase 6)**: Depends on US1 complete + +### User Story Dependencies + +- **User Story 1 (P1)**: No dependencies - can start immediately +- **User Story 2 (P2)**: No dependencies - can start in parallel with US1 +- **User Story 3 (P3)**: Depends on US1 (workflow must exist to add version sync) + +### Parallel Opportunities + +- US1 and US2 can be implemented in parallel (different files) +- T009 and T010 within US2 can run in parallel + +--- + +## Parallel Example: User Stories 1 & 2 + +```bash +# These can run simultaneously: +Agent A: "Create release workflow in .github/workflows/release.yml" (US1) +Agent B: "Create RELEASE.md documentation in docs/RELEASE.md" (US2) +``` + +--- + +## Implementation Strategy + +### MVP First (User Story 1 Only) + +1. Complete T001 (verify existing) +2. Complete T002-T008 (core workflow) +3. **STOP and VALIDATE**: Push test tag, verify release created +4. Merge and test on main branch + +### Incremental Delivery + +1. US1 → Working tag-triggered releases +2. US2 → Documentation for team self-service +3. US3 → Package.json version sync + +### Suggested Execution Order + +Single developer: +1. T001 → T002-T008 (MVP workflow) +2. T009-T012 (documentation in parallel-friendly commits) +3. T013-T016 (version sync) +4. T017-T018 (polish) + +--- + +## Notes + +- All workflow tasks in US1 affect same file - execute sequentially +- Documentation tasks (US2) can be committed independently +- Test by pushing tag after workflow is merged to main +- No unit tests - infrastructure validated through actual tag push From ae6c56f80350f17741c8dbebf394d070f41bd30d Mon Sep 17 00:00:00 2001 From: Ian Mayo Date: Sat, 29 Nov 2025 09:55:19 +0000 Subject: [PATCH 3/3] feat: add release automation workflow and documentation - Add .github/workflows/release.yml for tag-triggered releases - Trigger: push vX.Y.Z tag to main branch - CI validation: lint, test, build must pass before release - Auto-generates release notes from commits - Attaches bundle artifacts (sonar-quiz.iife.js, source map) - Syncs package.json version with tag version - Add docs/RELEASE.md with complete release instructions - Update README.md with release process section Closes #88 --- .github/workflows/release.yml | 115 ++++++++++++++++++++++ README.md | 12 +++ docs/RELEASE.md | 133 ++++++++++++++++++++++++++ specs/011-release-automation/tasks.md | 36 +++---- 4 files changed, 278 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 docs/RELEASE.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..ae2d97c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,115 @@ +name: Release + +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + +permissions: + contents: write + +jobs: + lint: + name: Lint & Format Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '22' + cache: 'npm' + - run: npm ci + - run: npm run lint + - run: npm run format:check + + test: + name: Unit & Integration Tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '22' + cache: 'npm' + - run: npm ci + - run: npm run test:unit + - run: npm run test:integration + + build: + name: Build & Bundle Size Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '22' + cache: 'npm' + - run: npm ci + - run: npm run build + - name: Check bundle size + run: npm run size-check + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: dist + path: dist/ + + release: + name: Create GitHub Release + runs-on: ubuntu-latest + needs: [lint, test, build] + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: dist + path: dist/ + + - name: Extract version from tag + id: version + run: | + VERSION=${GITHUB_REF_NAME#v} + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Releasing version: $VERSION" + + - name: Check if package.json version needs update + id: check-version + run: | + CURRENT_VERSION=$(node -p "require('./package.json').version") + TAG_VERSION=${{ steps.version.outputs.version }} + if [ "$CURRENT_VERSION" = "$TAG_VERSION" ]; then + echo "needs_update=false" >> $GITHUB_OUTPUT + echo "Package.json already at version $TAG_VERSION" + else + echo "needs_update=true" >> $GITHUB_OUTPUT + echo "Package.json version $CURRENT_VERSION differs from tag $TAG_VERSION" + fi + + - name: Update package.json version + if: steps.check-version.outputs.needs_update == 'true' + run: | + npm version ${{ steps.version.outputs.version }} --no-git-tag-version + echo "Updated package.json to version ${{ steps.version.outputs.version }}" + + - name: Commit and push version update + if: steps.check-version.outputs.needs_update == 'true' + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add package.json package-lock.json + git commit -m "chore(release): ${{ github.ref_name }}" + git push origin HEAD:main + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + generate_release_notes: true + files: | + dist/sonar-quiz.iife.js + dist/sonar-quiz.iife.js.map + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 9f530a4..1d3c718 100644 --- a/README.md +++ b/README.md @@ -123,10 +123,22 @@ npm run build:dita This copies `dist/sonar-quiz.iife.js` to `dita/template/resources/` for inclusion in WebHelp output. See [dita/README.md](./dita/README.md) for DITA authoring guidelines and template customization. +## Releases + +Releases are created by pushing a version tag to the main branch: + +```bash +git tag v0.2.0 +git push origin v0.2.0 +``` + +See [docs/RELEASE.md](./docs/RELEASE.md) for complete release instructions. + ## Project Documentation | Document | Description | |----------|-------------| +| [docs/RELEASE.md](./docs/RELEASE.md) | Release process and versioning guide | | [System_Requirements.md](./System_Requirements.md) | Functional requirements, user roles, data model, and authoring rules | | [Technical_Design.md](./Technical_Design.md) | Architecture, technology decisions, packaging, integration, and acceptance criteria | | [ARCHITECTURE_FLOWS.md](./ARCHITECTURE_FLOWS.md) | Event flows, login processes, DOM patterns, and service interactions | diff --git a/docs/RELEASE.md b/docs/RELEASE.md new file mode 100644 index 0000000..a982753 --- /dev/null +++ b/docs/RELEASE.md @@ -0,0 +1,133 @@ +# Release Process + +This document describes how to create releases for the BrowserTest (Sonar Quiz System) project. + +## Overview + +Releases are automated via GitHub Actions. When you push a version tag to the main branch, a workflow automatically: + +1. Runs all CI checks (lint, tests, build) +2. Builds the production bundle +3. Creates a GitHub Release with release notes +4. Attaches the bundle artifacts + +## Versioning + +This project uses [Semantic Versioning](https://semver.org/): + +- **MAJOR** (`X.0.0`): Breaking changes +- **MINOR** (`0.X.0`): New features (backward-compatible) +- **PATCH** (`0.0.X`): Bug fixes (backward-compatible) + +## How to Create a Release + +### Prerequisites + +- You must have push access to the repository +- The main branch must be in a passing CI state + +### Steps + +1. **Ensure you're on the latest main branch:** + + ```bash + git checkout main + git pull origin main + ``` + +2. **Create and push a version tag:** + + ```bash + git tag v0.2.0 + git push origin v0.2.0 + ``` + +3. **Monitor the release workflow:** + - Go to the [Actions tab](../../actions) + - Watch the "Release" workflow complete (~3-5 minutes) + +4. **Verify the release:** + - Go to the [Releases page](../../releases) + - Confirm the new release exists with: + - Correct version number + - Auto-generated release notes + - Attached `sonar-quiz.iife.js` bundle + - Attached `sonar-quiz.iife.js.map` source map + +### Using GitHub CLI + +```bash +# Create tag and release in one command +gh release create v0.2.0 --generate-notes +``` + +## Version Tag Format + +Tags **must** follow semantic versioning format: `vX.Y.Z` + +| Valid Tags | Invalid Tags | +|------------|--------------| +| `v0.1.0` | `0.1.0` (missing 'v' prefix) | +| `v1.0.0` | `v1.0` (missing patch number) | +| `v10.20.30` | `release-1.0.0` (wrong prefix) | +| `v2.0.0-beta.1` | N/A (pre-release not currently supported) | + +## What's Included in a Release + +Each release includes: + +- **sonar-quiz.iife.js** - The production bundle (IIFE format) +- **sonar-quiz.iife.js.map** - Source map for debugging +- **Source code** - Automatically generated zip and tar.gz archives + +## Troubleshooting + +### Tag pushed but no release created + +1. **Check tag format** - Must match `vX.Y.Z` pattern exactly +2. **Verify tag was pushed:** + ```bash + git ls-remote --tags origin | grep v0.2.0 + ``` +3. **Check Actions tab** - Look for workflow failures +4. **Review CI status** - Release won't be created if lint/tests/build fail + +### CI checks failing after tag push + +The release workflow runs the full CI suite. If it fails: + +1. Fix the issues on main branch +2. Delete the failed tag: + ```bash + git push --delete origin v0.2.0 + git tag -d v0.2.0 + ``` +3. Create the tag again after fixes are merged + +### Re-releasing the same version + +If you need to re-release (e.g., release was incomplete): + +```bash +# Delete the existing release +gh release delete v0.2.0 --yes + +# Delete the remote tag +git push --delete origin v0.2.0 + +# Delete local tag +git tag -d v0.2.0 + +# Create new tag and push +git tag v0.2.0 +git push origin v0.2.0 +``` + +### Package.json version mismatch + +The release workflow automatically updates `package.json` to match the tag version. If there's a mismatch, the tag version is the source of truth. + +## Related Documentation + +- [CLAUDE.md](../CLAUDE.md) - Development guidelines and project architecture +- [README.md](../README.md) - Project overview and quick start diff --git a/specs/011-release-automation/tasks.md b/specs/011-release-automation/tasks.md index c15402c..d9cb524 100644 --- a/specs/011-release-automation/tasks.md +++ b/specs/011-release-automation/tasks.md @@ -19,7 +19,7 @@ **Purpose**: No setup required - project already has GitHub Actions infrastructure -- [ ] T001 Verify existing CI workflow structure in .github/workflows/ci.yml +- [x] T001 Verify existing CI workflow structure in .github/workflows/ci.yml **Checkpoint**: Existing infrastructure confirmed @@ -43,13 +43,13 @@ ### Implementation for User Story 1 -- [ ] T002 [US1] Create release workflow file with tag push trigger (v[0-9]+.[0-9]+.[0-9]+) in .github/workflows/release.yml -- [ ] T003 [US1] Add CI validation jobs (lint, test, build) reusing patterns from ci.yml in .github/workflows/release.yml -- [ ] T004 [US1] Add version extraction step from GITHUB_REF_NAME in .github/workflows/release.yml -- [ ] T005 [US1] Add GitHub Release creation using softprops/action-gh-release in .github/workflows/release.yml -- [ ] T006 [US1] Configure release notes auto-generation from commits in .github/workflows/release.yml -- [ ] T007 [US1] Configure artifact upload (sonar-quiz.iife.js, source map) as release assets in .github/workflows/release.yml -- [ ] T008 [US1] Add permissions block for contents:write in .github/workflows/release.yml +- [x] T002 [US1] Create release workflow file with tag push trigger (v[0-9]+.[0-9]+.[0-9]+) in .github/workflows/release.yml +- [x] T003 [US1] Add CI validation jobs (lint, test, build) reusing patterns from ci.yml in .github/workflows/release.yml +- [x] T004 [US1] Add version extraction step from GITHUB_REF_NAME in .github/workflows/release.yml +- [x] T005 [US1] Add GitHub Release creation using softprops/action-gh-release in .github/workflows/release.yml +- [x] T006 [US1] Configure release notes auto-generation from commits in .github/workflows/release.yml +- [x] T007 [US1] Configure artifact upload (sonar-quiz.iife.js, source map) as release assets in .github/workflows/release.yml +- [x] T008 [US1] Add permissions block for contents:write in .github/workflows/release.yml **Checkpoint**: Release workflow functional - tag push creates release with artifacts @@ -63,10 +63,10 @@ ### Implementation for User Story 2 -- [ ] T009 [P] [US2] Create RELEASE.md with overview section explaining semantic versioning in docs/RELEASE.md -- [ ] T010 [P] [US2] Add "How to Create a Release" section with git tag commands in docs/RELEASE.md -- [ ] T011 [US2] Add version format requirements (vX.Y.Z pattern) in docs/RELEASE.md -- [ ] T012 [US2] Add troubleshooting section for common issues in docs/RELEASE.md +- [x] T009 [P] [US2] Create RELEASE.md with overview section explaining semantic versioning in docs/RELEASE.md +- [x] T010 [P] [US2] Add "How to Create a Release" section with git tag commands in docs/RELEASE.md +- [x] T011 [US2] Add version format requirements (vX.Y.Z pattern) in docs/RELEASE.md +- [x] T012 [US2] Add troubleshooting section for common issues in docs/RELEASE.md **Checkpoint**: Documentation complete - any maintainer can self-service release process @@ -80,10 +80,10 @@ ### Implementation for User Story 3 -- [ ] T013 [US3] Add package.json version update step extracting version from tag in .github/workflows/release.yml -- [ ] T014 [US3] Add git commit for version update with message "chore(release): vX.Y.Z" in .github/workflows/release.yml -- [ ] T015 [US3] Add git push to main branch for version commit in .github/workflows/release.yml -- [ ] T016 [US3] Handle edge case: skip version commit if package.json already matches tag in .github/workflows/release.yml +- [x] T013 [US3] Add package.json version update step extracting version from tag in .github/workflows/release.yml +- [x] T014 [US3] Add git commit for version update with message "chore(release): vX.Y.Z" in .github/workflows/release.yml +- [x] T015 [US3] Add git push to main branch for version commit in .github/workflows/release.yml +- [x] T016 [US3] Handle edge case: skip version commit if package.json already matches tag in .github/workflows/release.yml **Checkpoint**: Package.json stays in sync with release tags @@ -93,8 +93,8 @@ **Purpose**: Edge cases and final validation -- [ ] T017 Update README.md with release process reference and link to docs/RELEASE.md -- [ ] T018 Test by pushing test tag on feature branch to validate workflow syntax before merge +- [x] T017 Update README.md with release process reference and link to docs/RELEASE.md +- [x] T018 Test by pushing test tag on feature branch to validate workflow syntax before merge ---