Skip to content

Release 0.2.2#40

Merged
c-vigo merged 96 commits intomainfrom
release/0.2.2
Feb 26, 2026
Merged

Release 0.2.2#40
c-vigo merged 96 commits intomainfrom
release/0.2.2

Conversation

@vig-os-release-app
Copy link
Copy Markdown
Contributor

Release 0.2.2

This PR prepares release 0.2.2 for merge to main.

Release Content

Added

  • Exported shiftHeadersToMinLevel utility function for independent unit testing
  • Sync sub-issue relationships into frontmatter (#8, #15)
    • Fetch parent and subIssues via GraphQL batch query for all synced issues
    • New sync-sub-issues action input to control sub-issue syncing (default: true)
    • Replace hardcoded relationship: none with dynamic parent and children fields
    • Graceful degradation: emits info message and falls back to none if the sub-issues API is unavailable
  • CI/CD pipeline (#13)
    • CI workflow with lint, build-dist verification, and test jobs
    • Integration test suite as a reusable workflow with parallel jobs covering issues-only, PRs-only, force-update, include-closed, sub-issues, updated-since, state-file, and default-mode scenarios
    • Three-phase release pipeline: prepare-release (branch + draft PR), release (tag + GitHub Release with provenance attestation), and post-release (dev sync + CHANGELOG reset)
    • setup-env and build-dist composite actions for consistent environment setup
    • CHANGELOG management CLI (prepare_changelog.py) for automated release note preparation
    • Dependabot configuration for automated dependency updates
    • CODEOWNERS file for automated review assignment
    • CodeQL analysis workflow for automated security vulnerability scanning
    • Scorecard workflow for ongoing supply-chain security assessments
    • Security scan workflow for continuous security monitoring

Changed

  • Sync-issues workflow uses local action checkout (#13)
    • Replaced pinned remote ref with uses: ./ so the workflow always tests the current branch's code
  • Node.js version pinned via .nvmrc (#13)
    • .nvmrc is the single source of truth; setup-env and devcontainer read from it

Fixed

  • Corrected heading hierarchy in formatPRAsMarkdown: promoted the Comments section header from ## to # and individual comment entry headers from ### to ##
  • Release workflow avoids immutable-release upload failures
    • Generates checksums-sha256.txt before creating the GitHub release and attaches it during gh release create instead of uploading afterward
  • Release workflow: floating-tag updates and rollback (#38)
    • Floating-tag updates (vX, vX.Y) run in a separate job after the release job succeeds; main rollback no longer restores floating tags
    • Resolve floating tags via exact "Get a reference" API (git/ref/tags/$TAG) instead of git/matching-refs to avoid wrong-SHA from prefix matches
    • New job captures current SHAs, updates tags, and on failure restores from captured SHAs (self-contained)
  • --force-update does not re-sync issues (only PRs) (#10)
    • Added force-update action input that bypasses the hasContentChanged content-comparison gate
    • When active, all fetched items are re-written (with updated synced: frontmatter) even if body content is unchanged
    • Updated sync-issues.yml workflow to pass the force-update dispatch input to the action
  • Added shiftHeadersToMinLevel helper to re-level headers inside comment bodies so the shallowest header maps to ###, preventing collisions with outer document structure
  • Fixed default GITHUB_REPOSITORY in test-local.sh from non-existent vig-os/actions to vig-os/sync-issues-action
  • Removed broken fallback command in test-local.sh that passed a file path where a directory is required

Security

  • CodeQL and OpenSSF Scorecard analysis workflows (#13)
    • CodeQL scans JavaScript/TypeScript on push and PR
    • Scorecard publishes results to the Security tab via SARIF

Testing Checklist

  • All tests pass (npm run test:coverage)
  • Manual testing complete
  • No critical bugs found
  • Ready for release

When Ready to Release

Run the Release workflow (workflow_dispatch) with version 0.2.2.

This will:

  • Bump package.json version
  • Set release date in CHANGELOG
  • Run full test suite on finalized code
  • Create release tag (v0.2.2) and GitHub Release
  • Attest build provenance

Related

c-vigo and others added 30 commits February 18, 2026 16:30
Comment bodies in formatPRAsMarkdown were inserted verbatim, so headers
like `## Idea` inside a `### [Comment #N]` block broke the heading
hierarchy. Promote the section/comment chrome by one level (## → #,
### → ##) and pipe each comment body through a new shiftHeadersToMinLevel
helper that ensures the shallowest header starts at level 3.

Refs: #4
Fix the default GITHUB_REPOSITORY from the non-existent 'vig-os/actions'
to the correct 'vig-os/sync-issues-action', which caused a Not Found error
when running the local integration test. Also remove the broken fallback
command that passed a file path where a directory is required, producing
a misleading 'missing required argument' error.

Refs: #4
fix: shift PR comment headers to respect document hierarchy

Refs: #4
Add IssueRelationship interface. Update formatIssueAsMarkdown to accept
optional relationship data and render parent/children fields. Update PR
frontmatter to use parent/children instead of relationship.

Refs: #8
Query parentIssue and subIssues for all synced issues in batches of 50
using aliased GraphQL fields. Gracefully degrades to empty map on error.

Refs: #8
Collect all issue numbers first, fetch relationships in a single GraphQL
batch, then pass relationship data to formatIssueAsMarkdown for each
issue. Gracefully degrades when GraphQL is unavailable.

Refs: #8
## Summary

- Merges `main` into `dev` to bring the dev branch up to date with latest changes on main (3 commits: synced issues/PRs docs, merge PRs #1 and #3).

Part of #6

## Test plan

- [ ] PR merges cleanly into `dev`
- [ ] No regressions in existing functionality

Refs: #6
Sub-issue relationships are an issues-only concept; including them in PR
frontmatter adds noise with no possible value.

Refs: #8
## Description

Sync GitHub sub-issue relationships (`parentIssue`/`subIssues`) into the markdown frontmatter of synced issue files. Previously the action wrote a hardcoded `relationship: none` for every issue. This PR replaces that with two dynamic fields (`parent`, `children`) populated via a bulk GraphQL query using the `sub_issues` preview API.

## Related Issue(s)

Closes #8

## Type of Change

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Documentation update
- [ ] Refactoring (no functional changes)
- [ ] CI / Build change
- [ ] Test updates

## Changes Made

- **New `IssueRelationship` interface** — `{ parent: number | null; children: number[] }`
- **New `fetchIssueRelationships()` function** — Constructs batched (50 per query) aliased GraphQL queries to fetch `parentIssue` and `subIssues` for all synced issues in a single round-trip. Requires the `GraphQL-Features: sub_issues` header. Gracefully degrades to empty map on error.
- **Updated `syncIssuesToMarkdown()`** — Collects all issue numbers first, fetches relationships in bulk, then passes relationship data to each issue's formatting call.
- **Updated `formatIssueAsMarkdown()`** — Accepts optional `IssueRelationship` parameter; renders `parent: <N|none>` and `children: <N, M|none>` instead of `relationship: none`.
- **Updated PR frontmatter** — Replaced `relationship: none` with `parent: none` and `children: none`.
- **Updated test mock** — Added `graphql: jest.fn()` to the mocked Octokit instance.
- **8 new tests** — 4 formatting tests (parent-only, children-only, both, none), 3 fetch tests (happy path, empty list, error), 1 integration test (relationships in written files).

## Changelog Entry

### Added

- **Sync sub-issue relationships into frontmatter** ([#8](#8))
  - Fetch `parentIssue` and `subIssues` via GraphQL batch query for all synced issues
  - Replace hardcoded `relationship: none` with dynamic `parent` and `children` fields
  - Graceful degradation: falls back to `none` if GraphQL query fails

## Testing

- [x] Tests pass locally (`npm test` — 87 passed, 0 failed)
- [ ] Manual testing performed (describe below)

### Manual Testing Details

Unit tests cover all paths:
- `formatIssueAsMarkdown` with parent-only, children-only, both, and no relationships
- `fetchIssueRelationships` happy path (returns correct map), empty input (no GraphQL call), error handling (warning + empty map)
- Integration: `run()` with mocked GraphQL response verifies `parent: 2` and `children: 10, 11` appear in written file content

## Checklist

- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have updated the documentation accordingly (edit `docs/templates/`, then run `just docs`)
- [x] I have updated `CHANGELOG.md` in the `[Unreleased]` section (and pasted the entry above)
- [x] My changes generate no new warnings or errors
- [x] I have added tests that prove my fix is effective or that my feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published

## Additional Notes

- The issue originally referenced `trackedIssues`/`trackedInIssues` GraphQL fields, but GitHub retired tasklists in April 2025. This PR uses the replacement `subIssues`/`parentIssue` API with the `GraphQL-Features: sub_issues` header.
- The old `relationship` frontmatter field has been removed entirely — it was always `none` and is fully derivable from `parent`/`children`.
- Sub-issues support up to 100 children per parent and 8 nesting levels. The batch query fetches up to 100 children per issue.

Refs: #8
When force-update is true, syncIssuesToMarkdown and syncPRsToMarkdown
skip the content-comparison check and always write files. This ensures
all items are re-synced (with updated frontmatter timestamps) even when
their body content has not changed on GitHub.

Issue: #10
## Description

When triggering a workflow with `force-update: true`, only PRs were re-synced while issues were silently skipped. The root cause is that `hasContentChanged` strips frontmatter (including the `synced:` timestamp) and compares body content only -- when nothing has changed on GitHub, the body is identical and the write is skipped, even during a force-update. The action had no mechanism to bypass this content-comparison gate.

This PR adds a `force-update` boolean input to the action. When active, both `syncIssuesToMarkdown` and `syncPRsToMarkdown` skip the `hasContentChanged` check and always write files (updating the `synced:` frontmatter timestamp, which produces a real git diff).

## Related Issue(s)

Closes #10

## Type of Change

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [x] Documentation update
- [ ] Refactoring (no functional changes)
- [ ] CI / Build change
- [x] Test updates

## Changes Made

- `action.yml` -- added `force-update` input (boolean string, default `'false'`)
- `src/index.ts` -- read the new input, thread a `forceUpdate` boolean into `syncIssuesToMarkdown` and `syncPRsToMarkdown`, short-circuit with `forceUpdate || hasContentChanged(...)`
- `.github/workflows/sync-issues.yml` -- pass `force-update: ${{ github.event.inputs.force-update }}` to the action
- `src/__tests__/unit/index.test.ts` -- two new tests (issues + PRs) verifying force-update bypasses `hasContentChanged`
- `CHANGELOG.md` -- added entry under Unreleased > Fixed
- `README.md` -- added `force-update` row to the Options table

## Changelog Entry

### Fixed

- **`--force-update` does not re-sync issues (only PRs)** ([#10](#10))
  - Added `force-update` action input that bypasses the `hasContentChanged` content-comparison gate
  - When active, all fetched items are re-written (with updated `synced:` frontmatter) even if body content is unchanged
  - Updated `sync-issues.yml` workflow to pass the `force-update` dispatch input to the action

## Testing

- [x] Tests pass locally (`npx jest` -- 89 passed, 0 failed)
- [x] Manual testing performed (describe below)

### Manual Testing Details

- Ran `npx jest -t "force-update input"` to verify both new tests pass (issue + PR force-update)
- Ran `npx jest -t "should skip writing when only synced timestamp changes"` to confirm existing behaviour is preserved when `force-update` is not set

## Checklist

- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have updated the documentation accordingly
- [x] I have updated `CHANGELOG.md` in the `[Unreleased]` section (and pasted the entry above)
- [x] My changes generate no new warnings or errors
- [x] I have added tests that prove my fix is effective or that my feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published

## Additional Notes

The fix follows TDD: failing tests were committed first, then the implementation, then the workflow and docs updates. The commit history proves compliance:

1. `test:` failing test for issues
2. `test:` failing test for PRs
3. `fix:` implementation (action.yml + src/index.ts)
4. `fix:` workflow update
5. `docs:` changelog
6. `docs:` README

Refs: #10
- Pin hook revs to full SHAs for reproducibility
- Add branch naming enforcement and action SHA-pinning hooks
- Simplify ruff hooks, remove hadolint and checkmake
- Tighten pymarkdown rules (line length 120, front matter, ATX headings)

Refs: #13
Replace the three generic templates (bug_report, feature_request, task)
with purpose-built templates for each issue type: bug, feature, refactor,
chore, docs, discussion, and config contact link.

Refs: #13
Add CODEOWNERS to enforce review by the maintainer on all files.

Update the PR template to align with this project:
- Add type-of-change checklist using conventional commit types
- Add Changelog Entry section with an example referencing this repo
- Replace `make test` with `npm test`
- Remove stale `just docs` reference
- Add Refs traceability footer

Refs: #13
Enable weekly automated dependency updates for GitHub Actions (sha-pinned)
and npm packages, targeting the dev branch with grouped minor/patch updates.

Refs: #13
c-vigo and others added 24 commits February 23, 2026 12:39
## Summary

- Switch `prepare-release.yml`, `release.yml`, and `post-release.yml` from `APP_SYNC_ISSUES_*` secrets to `RELEASE_APP_*` secrets, pointing to a dedicated GitHub App with the required permissions (`contents:write`, `pull-requests:write`, `issues:write`).
- The previous fix (#20, commit ffe9e9b) misdiagnosed the root cause: it switched the PR creation step to `github.token`, but that token also cannot create PRs when the repo setting "Allow GitHub Actions to create and approve pull requests" is disabled. The correct fix is to use an App token from an App that has `pull-requests:write` permission.

## Test plan

- [x] Verify `RELEASE_APP_ID` and `RELEASE_APP_PRIVATE_KEY` secrets are configured
- [ ] Re-run the Prepare Release workflow and confirm the draft PR is created successfully

Refs: #18
Prepare CHANGELOG.md structure for version 0.2.0.
Release date TBD (set during finalization).
## Description

Sync main into release 0.2.0

## Type of Change

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [x] Documentation update
- [x] Refactoring (no functional changes)
- [ ] Test updates

## Changes Made

- Sync documentation (CHANGELOG, README, issues and PRs)
- Sync CI placeholders

## Testing

- [x] Tests pass locally (`npm run test:all`)
 
## Checklist

- [ ] My code follows the project's style guidelines
- [ ] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [x] I have updated the documentation accordingly (README.md, CONTRIBUTE.md, etc.)
- [x] I have updated the CHANGELOG.md in the `[Unreleased]` section
- [x] My changes generate no new warnings or errors
- [ ] I have added tests that prove my fix is effective or that my feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published

## Additional Notes

Refs: #22
# Conflicts:
#	.github/actions/setup-env/action.yml
#	.github/workflows/ci.yml
#	.github/workflows/codeql.yml
#	.github/workflows/post-release.yml
#	.github/workflows/prepare-release.yml
#	.github/workflows/release.yml
#	.github/workflows/scorecard.yml
#	CHANGELOG.md
#	docs/issues/issue-10.md
#	docs/pull-requests/pr-16.md
#	docs/pull-requests/pr-20.md
## Description

Sync main into release 0.2.0

## Type of Change

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [x] Documentation update
- [x] Refactoring (no functional changes)
- [ ] Test updates

## Changes Made

- Sync documentation (CHANGELOG, README, issues and PRs)
- Sync CI placeholders

## Testing

- [x] Tests pass locally (`npm run test:all`)
 
## Checklist

- [ ] My code follows the project's style guidelines
- [ ] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [x] I have updated the documentation accordingly (README.md, CONTRIBUTE.md, etc.)
- [x] I have updated the CHANGELOG.md in the `[Unreleased]` section
- [x] My changes generate no new warnings or errors
- [ ] I have added tests that prove my fix is effective or that my feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published

## Additional Notes

Refs: #22
The function signature defaulted syncSubIssues to false while
action.yml defaults sync-sub-issues to true. Although the caller
always passes the value explicitly (no runtime impact), the mismatch
could cause incorrect behavior if the function were ever called
without the argument.

Refs: #26
…lure (#25)

Move try/catch inside the batch loop so that:
- Schema errors ("doesn't exist on type") break immediately
- Transient errors warn per-batch and continue to the next
- Successfully fetched relationships are preserved instead of
  being discarded on a later batch failure

Add tests for multi-batch partial-result and schema-error-break
scenarios.
## Summary

- Fixes the `syncSubIssues` parameter default in `syncIssuesToMarkdown` from `false` to `true`, matching the `action.yml` `sync-sub-issues` input default
- Update README with full build pipeline

## Test plan

- [x] No runtime impact (caller always passes the value explicitly)
- [x] `npm run prepare` rebuilds cleanly
- [x] Existing tests pass (`npm test`)

Refs: #26
…ailure

## Summary

- Moves `try/catch` inside the batch loop in `fetchIssueRelationships` so each batch is handled independently
- Schema errors (`"doesn't exist on type"`) `break` immediately (API unavailable, no point continuing)
- Transient errors `warn` per-batch and `continue` to the next, preserving already-fetched relationships
- Exports `GRAPHQL_BATCH_SIZE` for testability
- Adds two new tests: multi-batch partial results on transient error, and schema-error break with partial results

## Test plan

- [x] All 95 existing unit tests pass
- [x] New partial-result tests cover both transient-error and schema-error scenarios
- [x] `npm run prepare` rebuilds cleanly
- [x] CI passes

Refs: #25
## Summary
- Clarifies the weekly CodeQL schedule comment in `.github/workflows/codeql.yml`
- Makes explicit that the scheduled run re-scans with updated CodeQL rules/engines even when repository code has not changed
- Removes ambiguity noted in PR #22 review discussion

## Test plan
- [x] Confirm only workflow comments changed (no runtime workflow logic changes)
- [x] Validate YAML remains syntactically valid
- [x] Verify wording addresses reviewer question about schedule purpose

Refs: #29
## Description
Fix release workflow validation failure in dry-run mode by allowing the reusable integration test workflow to request required read scopes.

## Type of Change
- [x] `fix` -- Bug fix
- [ ] `ci` -- CI/CD pipeline changes

### Modifiers
- [ ] Breaking change (`!`) -- This change breaks backward compatibility

## Changes Made
- Added job-level permissions to `integration-test` in `.github/workflows/release.yml`
- Granted only minimum required scopes: `contents: read`, `issues: read`, `pull-requests: read`

## Changelog Entry
No changelog needed (workflow permission fix only).

## Testing
- [x] Tests pass locally (`npm test`)
- [x] Manual testing performed (describe below)

### Manual Testing Details
- Verified workflow schema error cause against reusable workflow requested permissions.
- Confirmed caller now explicitly allows required read scopes.

## Checklist
- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have updated the documentation accordingly
- [ ] I have updated `CHANGELOG.md` in the `[Unreleased]` section (and pasted the entry above)
- [x] My changes generate no new warnings or errors
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published

## Additional Notes
Scoped permissions are set only on the reusable workflow caller job to preserve least privilege.

Refs: #31
## Summary
- Merge `release/0.2.0` back into `dev` to realign branches after fixing issue #34 (immutable release errors).
- Retrigger the `prepare release` workflow from a clean state after the permissions/workflow fix.
- Preserve release workflow continuity without introducing new feature changes.

## Test plan
- [ ] Confirm PR merges cleanly into `dev`.
- [ ] Verify `prepare release` workflow triggers after merge.
- [ ] Verify workflow run completes without immutable release errors (issue #34).

Refs: #34
Attach checksums during `gh release create` instead of uploading after release creation to work with immutable releases.
Harden floating-tag SHA lookup/rollback by validating resolved SHAs before restore/delete operations.

Refs: #34
## Description

Fixes release publishing failures caused by immutable release state when uploading artifacts after release creation. The workflow now prepares checksum artifacts before release creation and hardens floating tag SHA resolution/rollback handling.

## Type of Change

- [ ] `feat` -- New feature
- [x] `fix` -- Bug fix
- [ ] `docs` -- Documentation only
- [ ] `chore` -- Maintenance task (deps, config, etc.)
- [ ] `refactor` -- Code restructuring (no behavior change)
- [ ] `test` -- Adding or updating tests
- [x] `ci` -- CI/CD pipeline changes
- [ ] `build` -- Build system or dependency changes
- [ ] `revert` -- Reverts a previous commit
- [ ] `style` -- Code style (formatting, whitespace)

### Modifiers

- [ ] Breaking change (`!`) -- This change breaks backward compatibility

## Changes Made

- Generate `checksums-sha256.txt` before creating the GitHub release.
- Attach checksums during `gh release create` instead of uploading after release creation.
- Resolve floating tags with `git/matching-refs/tags/*` and only accept valid 40-char SHAs.
- Skip rollback restore/delete operations when the previous SHA is present but invalid.
- Add corresponding `[Unreleased]` changelog entry.

## Changelog Entry

### Fixed

- **Release workflow avoids immutable-release upload failures**
  - Generates `checksums-sha256.txt` before creating the GitHub release and attaches it during `gh release create` instead of uploading afterward
  - Hardens floating-tag SHA handling by resolving tags via `git/matching-refs`, validating SHA format, and skipping invalid rollback SHAs

## Testing

- [ ] Tests pass locally (`npm test`)
- [x] Manual testing performed (describe below)

### Manual Testing Details

- Verified workflow logic changes by reviewing command flow in `.github/workflows/release.yml`.
- Confirmed release command now includes checksum asset at creation time.
- Confirmed tag SHA retrieval and rollback paths now validate SHA format.

## Checklist

- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [x] I have updated the documentation accordingly
- [x] I have updated `CHANGELOG.md` in the `[Unreleased]` section (and pasted the entry above)
- [x] My changes generate no new warnings or errors
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published

## Additional Notes

No functional changes outside the release workflow and changelog update.

Refs: #34
…xact ref

- Resolve each floating tag via the exact "Get a reference" API
  (GET repos/.../git/ref/tags/$TAG) so the SHA is for the exact tag.
- Run floating-tag updates in a dedicated job (update-floating-tags)
  that runs only after the release job succeeds. The main rollback job
  no longer captures or restores floating tags.
- CHANGELOG: add Fixed entry for #38

Refs: #38
…lution

## Description

Fixes release workflow errors when updating floating tags (vX, vX.Y): moves floating-tag updates to a separate job, resolves tags via the exact "Get a reference" API to avoid wrong SHA from prefix matches, and keeps rollback self-contained. Also fixes immutable release upload failures by generating and attaching `checksums-sha256.txt` during `gh release create`.

## Type of Change

- [x] `fix` -- Bug fix
- [ ] `feat` -- New feature
- [ ] `docs` -- Documentation only
- [ ] `chore` -- Maintenance task (deps, config, etc.)
- [ ] `refactor` -- Code restructuring (no behavior change)
- [ ] `test` -- Adding or updating tests
- [x] `ci` -- CI/CD pipeline changes
- [ ] `build` -- Build system or dependency changes
- [ ] `revert` -- Reverts a previous commit
- [ ] `style` -- Code style (formatting, whitespace)

### Modifiers

- [ ] Breaking change (`!`) -- This change breaks backward compatibility

## Changes Made

- **Floating-tag updates (#38):** Run in a separate job after the release job succeeds; main rollback no longer restores floating tags. Resolve floating tags via `GET /repos/{owner}/{repo}/git/ref/tags/{tag}` instead of matching-refs to avoid wrong SHA from prefix matches. New job captures current SHAs, updates tags, and on failure restores from captured SHAs (self-contained).
- **Immutable release uploads:** Generate `checksums-sha256.txt` before creating the GitHub release and attach it during `gh release create` instead of uploading afterward.

## Changelog Entry

```
### Fixed
- **Release workflow avoids immutable-release upload failures**
  - Generates `checksums-sha256.txt` before creating the GitHub release and attaches it during `gh release create` instead of uploading afterward
- **Release workflow: floating-tag updates and rollback** ([#38](#38))
  - Floating-tag updates (vX, vX.Y) run in a separate job after the release job succeeds; main rollback no longer restores floating tags
  - Resolve floating tags via exact "Get a reference" API (`git/ref/tags/$TAG`) instead of `git/matching-refs` to avoid wrong-SHA from prefix matches
  - New job captures current SHAs, updates tags, and on failure restores from captured SHAs (self-contained)
```

## Testing

- [x] Tests pass locally (`npm test`)
- [ ] Manual testing performed (describe below)

### Manual Testing Details

Release workflow changes validated via CI and release dry-run / integration test flows.

## Checklist

- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have updated the documentation accordingly
- [x] I have updated `CHANGELOG.md` in the `[Unreleased]` section (and pasted the entry above)
- [x] My changes generate no new warnings or errors
- [x] I have added tests that prove my fix is effective or that my feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published

## Additional Notes

Floating-tag update logic is isolated in a dedicated job so that release creation and asset uploads complete first; tag updates and their rollback are independent of the main release rollback.

Refs: #38
Prepare CHANGELOG.md structure for version 0.2.2.
Release date TBD (set during finalization).
@c-vigo c-vigo self-requested a review February 26, 2026 09:14
@c-vigo c-vigo marked this pull request as ready for review February 26, 2026 09:14
Set release date to 2026-02-26 in CHANGELOG.md
Bump package.json version to 0.2.2

Refs: #40
@c-vigo c-vigo merged commit 302e830 into main Feb 26, 2026
17 checks passed
@c-vigo c-vigo deleted the release/0.2.2 branch February 26, 2026 09:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant