From 1f9f03d1af98e2630eec238312d087e513fb2d67 Mon Sep 17 00:00:00 2001 From: Benjamin Kapner Date: Sun, 16 Aug 2026 14:21:27 +0300 Subject: [PATCH 1/5] chore(release): add release workflow, CHANGELOG, and version metadata Phase 1: Releases and versioning. 285 commits with zero releases means users must consume @main, which is an unbounded trust grant for an action with contents:write. Add a release workflow triggered on semver tag push that runs the full test suite, creates a GitHub Release with notes extracted from CHANGELOG.md, and force-updates the moving major tag (v0 -> v0.x.y). Seed CHANGELOG.md with a 0.1.0 entry summarising current capability. Set version in pyproject.toml as the single source of truth. Rewrite RELEASING.md to document the automated tag-push flow. --- .github/workflows/release.yml | 60 +++++++++++++++++++++++++ CHANGELOG.md | 30 +++++++++++++ RELEASING.md | 82 +++++++++++++++++------------------ pyproject.toml | 2 +- 4 files changed, 130 insertions(+), 44 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 CHANGELOG.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..8453e45 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,60 @@ +name: Release + +on: + push: + tags: + - "v*.*.*" + +permissions: + contents: write + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6 + - run: uv python install 3.12 + - run: uv sync --extra dev + - run: uv run ruff check src/ tests/ + - run: uv run ruff format --check src/ tests/ + - run: uv run pytest -v --cov=src --cov-report=term-missing --cov-fail-under=60 + + release: + needs: test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Extract version from tag + id: version + run: echo "tag=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT" + + - name: Extract changelog section + id: changelog + run: | + version="${{ steps.version.outputs.tag }}" + version="${version#v}" + # Extract the section for this version from CHANGELOG.md + section=$(awk "/^## \[${version}\]/{found=1; next} /^## \[/{if(found) exit} found{print}" CHANGELOG.md) + if [ -z "$section" ]; then + section="Release ${version}" + fi + # Use a delimiter for multiline output + echo "body<> "$GITHUB_OUTPUT" + echo "$section" >> "$GITHUB_OUTPUT" + echo "CHANGELOG_EOF" >> "$GITHUB_OUTPUT" + + - name: Create GitHub Release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create "${{ steps.version.outputs.tag }}" \ + --title "${{ steps.version.outputs.tag }}" \ + --notes "${{ steps.changelog.outputs.body }}" + + - name: Update major version tag + run: | + major=$(echo "${{ steps.version.outputs.tag }}" | grep -oP '^v\d+') + git tag -f "$major" + git push -f origin "$major" diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..936e9f7 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,30 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.1.0] - 2026-08-16 + +Initial tagged release. The action has been in use since September 2025; +this release captures the current feature set for stable pinning. + +### Added + +- AI-powered documentation review and update via PR comments + (`[review-docs]`, `[update-docs]`) +- Spec-vs-code gap analysis via Jira integration (`[review-feature]`) +- Support for Markdown, AsciiDoc, and reStructuredText doc formats +- Same-repo and separate-docs-repo configurations +- Semantic folder indexes for faster file discovery +- Persistent style guidelines via `.code-to-docs/style.md` +- Repository configuration via `.code-to-docs/config.json` +- Post-generation validation: diff-based preservation check and independent + LLM verification to prevent unrelated content deletion +- Interactive review with checkboxes for accepting/rejecting file suggestions +- Fork PR detection with suggested-changes fallback +- Per-file and global reviewer instructions in `[update-docs]` comments +- CI pipeline with ruff linting, formatting, and 60% coverage threshold diff --git a/RELEASING.md b/RELEASING.md index 0ec8bb2..293e9cd 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -2,66 +2,62 @@ This document explains how to release new versions of the code-to-docs action. -## Releasing a New Version - -When you're ready to release a new version (e.g., v1.2.0): - -### 1. Create and push the specific version tag +## How It Works -```bash -git tag v1.2.0 -git push origin v1.2.0 -``` +Pushing a semver tag triggers `.github/workflows/release.yml`, which: -### 2. Move the major version tag +1. Runs the full test suite (lint, format, tests with coverage) +2. Extracts the release notes from `CHANGELOG.md` +3. Creates a GitHub Release +4. Force-updates the moving major tag (e.g. `v0` points to `v0.1.0`) -This ensures users using `@v1` get the latest v1.x.x version: +## Releasing a New Version -```bash -git tag -f v1 # Move v1 tag to point to v1.2.0 -git push -f origin v1 # Force push the moved tag -``` +### 1. Update CHANGELOG.md -### 3. Update the README (if needed) +Move items from `[Unreleased]` into a new version section: -If the example in README.md references a specific version, consider whether it needs updating. +```markdown +## [0.2.0] - 2026-09-01 -## Version Numbering +### Added +- New feature description +``` -Follow semantic versioning (MAJOR.MINOR.PATCH): +### 2. Bump the version in pyproject.toml -- **MAJOR** (v2.0.0): Breaking changes -- **MINOR** (v1.2.0): New features, backward compatible -- **PATCH** (v1.1.1): Bug fixes, backward compatible +```toml +version = "0.2.0" +``` -## Complete Example +### 3. Commit, tag, and push ```bash -# Release v1.2.0 -git tag v1.2.0 -git push origin v1.2.0 +git add CHANGELOG.md pyproject.toml +git commit -m "chore(release): prepare v0.2.0" +git tag v0.2.0 +git push origin main --tags +``` -# Move v1 to v1.2.0 -git tag -f v1 -git push -f origin v1 +The release workflow handles the rest: it creates the GitHub Release and +moves the `v0` tag. -echo "✅ Released v1.2.0 and updated v1 tag" -``` +## Version Numbering -## Verification +Follow semantic versioning (MAJOR.MINOR.PATCH): -After releasing, verify users can access it: +- **MAJOR** (v1.0.0): Breaking changes to action inputs, outputs, or behavior +- **MINOR** (v0.2.0): New features, backward compatible +- **PATCH** (v0.1.1): Bug fixes, backward compatible -```bash -# Check tags -git ls-remote --tags origin | grep v1 +## What Users Pin To -# Should see both: -# refs/tags/v1.2.0 -# refs/tags/v1 -``` +- `@v0` receives all compatible updates (recommended) +- `@v0.1.0` is pinned to an exact release +- `@main` tracks unreleased changes (unstable, not recommended) -Users can now use: -- `redhat-community-ai-tools/code-to-docs@v1` (gets v1.2.0) -- `redhat-community-ai-tools/code-to-docs@v1.2.0` (pinned to v1.2.0) +## Marketplace +After the GitHub Release is created, visit the Release page and click +"Publish this Action to the GitHub Marketplace" if the listing is not yet +automatic. This is a manual step in the GitHub UI. diff --git a/pyproject.toml b/pyproject.toml index 3370ad9..9ae989d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "code-to-docs" -version = "0.0.0" +version = "0.1.0" description = "GitHub Action that generates documentation suggestions from code changes using LLMs" requires-python = ">=3.12" license = {text = "MIT"} From dba34375f86f0bb298de17301fbc47dc95d8a040 Mon Sep 17 00:00:00 2001 From: Benjamin Kapner Date: Sun, 16 Aug 2026 14:22:17 +0300 Subject: [PATCH 2/5] docs(readme): pin action to a released tag instead of @main Phase 1: Releases and versioning. uses: code-to-docs@main on an action that pushes commits to user branches is an unbounded trust grant. Pin the README workflow example to @v0 (the moving major tag from the release workflow) and add a Versioning section explaining the pinning options. --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 60a7e46..cb6969d 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,7 @@ jobs: "AUTHORIZATION: basic $(echo -n "x-access-token:${GH_TOKEN}" | base64 -w 0)" - name: Documentation Assistant - uses: redhat-community-ai-tools/code-to-docs@main + uses: redhat-community-ai-tools/code-to-docs@v0 with: model-api-base: ${{ secrets.MODEL_API_BASE }} model-api-key: ${{ secrets.MODEL_API_KEY }} @@ -198,6 +198,12 @@ These are set as `with:` parameters in the workflow step (not as secrets): |-------|-------------| | `style-config-path` | _(Optional)_ Path to a Markdown style configuration file (`.md`) containing documentation style guidelines. If not set, auto-detects `.code-to-docs/style.md`. | +### Versioning + +- `@v0` receives all backward-compatible updates (recommended) +- `@v0.1.0` pins to an exact release +- `@main` tracks unreleased changes and is not stable + ### Supported Model Backends Any OpenAI-compatible API works. Common examples: From f1f029ea125fec033e95f91dc12ae237f62bbadb Mon Sep 17 00:00:00 2001 From: csoceanu Date: Sun, 16 Aug 2026 17:23:17 +0300 Subject: [PATCH 3/5] chore: remove post-generation validation from v0.1.0 changelog PR #53 (post-generation validation) is not yet merged, so it should not be listed as a v0.1.0 feature. Will be added to the changelog when the PR is merged. Co-Authored-By: Claude Opus 4.6 (1M context) --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 936e9f7..d7d3815 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,8 +22,6 @@ this release captures the current feature set for stable pinning. - Semantic folder indexes for faster file discovery - Persistent style guidelines via `.code-to-docs/style.md` - Repository configuration via `.code-to-docs/config.json` -- Post-generation validation: diff-based preservation check and independent - LLM verification to prevent unrelated content deletion - Interactive review with checkboxes for accepting/rejecting file suggestions - Fork PR detection with suggested-changes fallback - Per-file and global reviewer instructions in `[update-docs]` comments From b39241af9894389609572f4f54385c7a32f43406 Mon Sep 17 00:00:00 2001 From: csoceanu Date: Sun, 16 Aug 2026 17:42:15 +0300 Subject: [PATCH 4/5] fix: pass step outputs through env vars to prevent script injection Use env: variables instead of ${{ }} interpolation in shell commands to prevent script injection from tag names or changelog content containing shell metacharacters. Also escape dots in awk regex for version matching. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/release.yml | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8453e45..6b3036f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,11 +32,14 @@ jobs: - name: Extract changelog section id: changelog + env: + TAG: ${{ steps.version.outputs.tag }} run: | - version="${{ steps.version.outputs.tag }}" - version="${version#v}" + version="${TAG#v}" + # Escape dots for awk regex + escaped=$(echo "$version" | sed 's/\./\\./g') # Extract the section for this version from CHANGELOG.md - section=$(awk "/^## \[${version}\]/{found=1; next} /^## \[/{if(found) exit} found{print}" CHANGELOG.md) + section=$(awk "/^## \[${escaped}\]/{found=1; next} /^## \[/{if(found) exit} found{print}" CHANGELOG.md) if [ -z "$section" ]; then section="Release ${version}" fi @@ -48,13 +51,17 @@ jobs: - name: Create GitHub Release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG: ${{ steps.version.outputs.tag }} + NOTES: ${{ steps.changelog.outputs.body }} run: | - gh release create "${{ steps.version.outputs.tag }}" \ - --title "${{ steps.version.outputs.tag }}" \ - --notes "${{ steps.changelog.outputs.body }}" + gh release create "$TAG" \ + --title "$TAG" \ + --notes "$NOTES" - name: Update major version tag + env: + TAG: ${{ steps.version.outputs.tag }} run: | - major=$(echo "${{ steps.version.outputs.tag }}" | grep -oP '^v\d+') + major=$(echo "$TAG" | grep -oP '^v\d+') git tag -f "$major" git push -f origin "$major" From 60d7b8143344d59b21c0e471e09bb8469c5bc700 Mon Sep 17 00:00:00 2001 From: csoceanu Date: Mon, 17 Aug 2026 10:22:59 +0300 Subject: [PATCH 5/5] chore: rename release.yml to release.yaml for consistency All existing workflow files use .yaml extension (ci.yaml, fullsend.yaml). Updates the reference in RELEASING.md as well. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/{release.yml => release.yaml} | 0 RELEASING.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{release.yml => release.yaml} (100%) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yaml similarity index 100% rename from .github/workflows/release.yml rename to .github/workflows/release.yaml diff --git a/RELEASING.md b/RELEASING.md index 293e9cd..2cb0fad 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -4,7 +4,7 @@ This document explains how to release new versions of the code-to-docs action. ## How It Works -Pushing a semver tag triggers `.github/workflows/release.yml`, which: +Pushing a semver tag triggers `.github/workflows/release.yaml`, which: 1. Runs the full test suite (lint, format, tests with coverage) 2. Extracts the release notes from `CHANGELOG.md`