Skip to content

Release 0.2.0#22

Closed
vig-os-release-app[bot] wants to merge 88 commits intomainfrom
release/0.2.0
Closed

Release 0.2.0#22
vig-os-release-app[bot] wants to merge 88 commits intomainfrom
release/0.2.0

Conversation

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

@vig-os-release-app vig-os-release-app Bot commented Feb 23, 2026

Release 0.2.0

This PR prepares release 0.2.0 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

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 ##
  • --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 local tests pass (npm run prepare && npm run test:all)
  • CI/CD tests pass (integration-test workflow)
  • Ready for release

When Ready to Release

Run the Release workflow (workflow_dispatch) with version 0.2.0.

This will:

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

Related

Refs: #4, #5, #6, #7, #8, #9, #10, #11, #12, #13, #14, #15, #16, #17, #18, #19, #20, #21, #22, #23, #24, #25, #26, #27, #28, #29, #30

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
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR prepares release 0.2.0, introducing sub-issue relationship syncing, force-update functionality, and a comprehensive CI/CD pipeline. The release addresses issues #8, #10, #13, and #15, adding GraphQL-based parent/child relationship tracking for issues and improving the testing and release infrastructure.

Changes:

  • Added GraphQL batch querying to sync sub-issue relationships (parent/children frontmatter fields)
  • Implemented force-update and sync-sub-issues action inputs with graceful API degradation
  • Established full CI/CD pipeline with integration tests, release automation, and security scanning
  • Fixed PR comment header hierarchy and removed source maps from build output

Reviewed changes

Copilot reviewed 46 out of 74 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/index.ts Core implementation: GraphQL relationship fetching, force-update bypass, frontmatter changes
action.yml New inputs: force-update, sync-sub-issues
tsconfig.json Disabled source/declaration maps
package.json Removed --source-map flag from package script
README.md Updated feature list to include relationships
CHANGELOG.md Prepared 0.2.0 release notes
.github/workflows/* Added/updated CI, CodeQL, Scorecard, integration-test, prepare-release, post-release workflows
.github/actions/* Added setup-env and build-dist composite actions
.pymarkdown Enhanced markdown linting configuration
.pre-commit-config.yaml Updated hooks with SHA pinning
.nvmrc Added Node.js version pinning
docs/* Synced issue and PR markdown files

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/index.ts Outdated
Comment thread src/index.ts Outdated
Comment thread src/index.ts Outdated
c-vigo and others added 7 commits February 23, 2026 15:53
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
@gerchowl
Copy link
Copy Markdown

gerchowl commented Feb 23, 2026

Id say the reason for it to exist is to allow dev to diverge while the release is being prepared. Once released i dont see the point in keeping it.

So anything dev has, should be fine.

A hotfix as in patch will bump the version X.Y.Z+1 so it should be a new rc anyway?!

Comment thread .github/workflows/codeql.yml
Copy link
Copy Markdown

@gerchowl gerchowl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing Checklist

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

update checklist or remove if not applicable

@c-vigo
Copy link
Copy Markdown
Contributor

c-vigo commented Feb 25, 2026

Testing Checklist

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

update checklist or remove if not applicable

Updated.
@gerchowl could you run the local tests too?

c-vigo and others added 2 commits February 25, 2026 11:35
## 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
Copy link
Copy Markdown

@gerchowl gerchowl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing Checklist

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

update checklist or remove if not applicable

Updated.
@gerchowl could you run the local tests too?

----------|---------|----------|---------|---------|------------------------------------------------------------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s                                                      
----------|---------|----------|---------|---------|------------------------------------------------------------------------
All files |   93.31 |    76.43 |      94 |      94 |                                                                        
 index.ts |   93.31 |    76.43 |      94 |      94 | 10-11,16,21-23,242,401-402,446,464-475,501-502,597,608,626,633,672,690 
----------|---------|----------|---------|---------|------------------------------------------------------------------------
Test Suites: 1 passed, 1 total
Tests:       95 passed, 95 total
Snapshots:   0 total
Time:        2.701 s, estimated 3 s
Ran all test suites.

vig-os-release-app Bot added a commit that referenced this pull request Feb 25, 2026
Set release date to 2026-02-25 in CHANGELOG.md
Bump package.json version to 0.2.0

Refs: #22
@c-vigo
Copy link
Copy Markdown
Contributor

c-vigo commented Feb 25, 2026

Due to immutability of releases, the bug described in #34 means version 0.2.0 is no longer available. We switch to 0.2.1.

@c-vigo c-vigo closed this Feb 25, 2026
@c-vigo c-vigo deleted the release/0.2.0 branch February 25, 2026 19:21
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.

3 participants