From b4bc78789b07ae04617f11dade879d4308710bf5 Mon Sep 17 00:00:00 2001 From: lukemun Date: Fri, 15 Aug 2025 13:38:22 -0400 Subject: [PATCH 1/4] feat: add comprehensive testing strategy - Add changelog-test.yml for testing PR changes locally - Add integration-test.yml with matrix tests for edge cases - Add release.sh script for automated version management - Update README with testing and release documentation This enables: - Dual workflow testing (prod vs PR version) - Automated integration tests - Streamlined release process with floating tags --- .github/workflows/changelog-test.yml | 61 +++++++++++++++++ .github/workflows/integration-test.yml | 94 ++++++++++++++++++++++++++ README.md | 26 +++++++ action.yml | 4 +- scripts/release.sh | 64 ++++++++++++++++++ 5 files changed, 247 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/changelog-test.yml create mode 100644 .github/workflows/integration-test.yml create mode 100755 scripts/release.sh diff --git a/.github/workflows/changelog-test.yml b/.github/workflows/changelog-test.yml new file mode 100644 index 0000000..8e81107 --- /dev/null +++ b/.github/workflows/changelog-test.yml @@ -0,0 +1,61 @@ +name: Test Changelog (PR Version) + +# This workflow tests the PR version of the action against itself +# It only runs when action code is modified + +on: + pull_request: + branches: [main] + types: [opened, synchronize, reopened, ready_for_review] + paths: + - "action.yml" + - "lib/**" + - "package.json" + - ".github/workflows/changelog-test.yml" + +permissions: + contents: write + pull-requests: write + issues: write + +jobs: + test-pr-version: + runs-on: ubuntu-latest + name: Test PR Version + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Test Changelog with PR Version + uses: ./ # Uses the local action code from this PR + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + changelog_path: "CHANGELOG.md" + target_name: "context-ledger-test" + version_increment: "auto" + auto_commit: false # Never auto-commit in test mode + create_pr_suggestions: true + continue-on-error: true + + - name: Report Test Status + if: always() + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const status = '${{ steps.test-changelog.outcome }}'; + const body = status === 'success' + ? 'โœ… **Test Passed**: PR version of Context Ledger ran successfully!' + : 'โš ๏ธ **Test Status**: PR version completed with status: ' + status; + + // Post a comment with test results + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: body + '\n\n*This is a test run using the PR version of the action.*' + }); diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml new file mode 100644 index 0000000..4110c5b --- /dev/null +++ b/.github/workflows/integration-test.yml @@ -0,0 +1,94 @@ +name: Integration Tests + +on: + pull_request: + branches: [main] + paths: + - "action.yml" + - "lib/**" + - "package.json" + workflow_dispatch: + +jobs: + test-scenarios: + runs-on: ubuntu-latest + strategy: + matrix: + test-case: + - name: "Empty Changelog" + changelog: | + # Changelog + + + - name: "Existing Versions" + changelog: | + # Changelog + + ## [1.0.0] - 2024-01-01 + - Initial release + + + - name: "Multiple Markers" + changelog: | + # Changelog + + ## [1.0.0] + + + ## [0.9.0] + + - name: "No Marker" + changelog: | + # Changelog + + ## [1.0.0] - 2024-01-01 + - Initial release + + name: Test - ${{ matrix.test-case.name }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + fetch-depth: 0 + + - name: Create test changelog + run: | + cat > test-CHANGELOG.md << 'EOF' + ${{ matrix.test-case.changelog }} + EOF + + - name: Run Context Ledger + id: changelog + uses: ./ + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + changelog_path: "test-CHANGELOG.md" + target_name: "test-${{ matrix.test-case.name }}" + version_increment: "patch" + auto_commit: false + create_pr_suggestions: false + continue-on-error: true + + - name: Validate Results + run: | + echo "Test Case: ${{ matrix.test-case.name }}" + echo "Status: ${{ steps.changelog.outputs.status }}" + echo "Updated: ${{ steps.changelog.outputs.changelog_updated }}" + echo "Version: ${{ steps.changelog.outputs.version_generated }}" + + # Show the resulting changelog + echo "=== Resulting Changelog ===" + cat test-CHANGELOG.md || echo "File not found" + + # Basic validation + if [ "${{ matrix.test-case.name }}" == "No Marker" ]; then + if [ "${{ steps.changelog.outputs.status }}" != "ERROR" ]; then + echo "โŒ Expected ERROR for no marker case" + exit 1 + fi + fi + + - name: Cleanup + if: always() + run: rm -f test-CHANGELOG.md diff --git a/README.md b/README.md index 6659663..c90be5d 100644 --- a/README.md +++ b/README.md @@ -430,6 +430,32 @@ npm test act pull_request -s ANTHROPIC_API_KEY=your_test_key ``` +## ๐Ÿงช Testing & Development + +### Testing Strategy + +Context Ledger uses a dual-workflow testing approach: + +1. **Production Testing** (`changelog.yml`): Uses the published version (`@v1`) +2. **PR Testing** (`changelog-test.yml`): Tests PR changes using local code (`./`) +3. **Integration Tests** (`integration-test.yml`): Matrix tests for edge cases + +### Release Process + +When ready to release a new version: + +```bash +# 1. Ensure CHANGELOG.md has the new version +# 2. Merge your PR to main +# 3. Run the release script +./scripts/release.sh +``` + +This will: +- Create a new version tag (e.g., `v1.0.19`) +- Update the floating major tag (e.g., `v1`) +- Push both tags to GitHub + ## ๐Ÿ›ก๏ธ Security - **API Key Security**: Store your Anthropic API key in GitHub Secrets, never in code diff --git a/action.yml b/action.yml index a5b17ec..457f898 100644 --- a/action.yml +++ b/action.yml @@ -207,7 +207,7 @@ runs: # Get current branch and recent tags CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) - + # Try to get latest version from CHANGELOG.md first LATEST_VERSION="" if [ -f "CHANGELOG.md" ]; then @@ -215,7 +215,7 @@ runs: # Matches lines like: ## [0.3.0] LATEST_VERSION=$(tac CHANGELOG.md | grep -m1 -E '^\#\# \[[0-9]+\.[0-9]+\.[0-9]+\]' | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || true) fi - + # If no version in changelog, try git tags if [ -z "$LATEST_VERSION" ]; then LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100755 index 0000000..3b7a403 --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# Release script for Context Ledger +# This automates the release process and ensures proper tagging + +set -e + +# Colors for output +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +echo -e "${GREEN}Context Ledger Release Process${NC}" +echo "=================================" + +# Check if we're on main branch +CURRENT_BRANCH=$(git branch --show-current) +if [ "$CURRENT_BRANCH" != "main" ]; then + echo -e "${RED}Error: Must be on main branch to release${NC}" + exit 1 +fi + +# Get the latest version from CHANGELOG.md +LATEST_VERSION=$(tac CHANGELOG.md | grep -m1 -E '^\#\# \[[0-9]+\.[0-9]+\.[0-9]+\]' | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0") +echo -e "${YELLOW}Latest version in CHANGELOG: v$LATEST_VERSION${NC}" + +# Get the latest git tag +LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") +echo -e "${YELLOW}Latest git tag: $LATEST_TAG${NC}" + +# Ensure we have a new version +if [ "v$LATEST_VERSION" == "$LATEST_TAG" ]; then + echo -e "${RED}Error: No new version found in CHANGELOG.md${NC}" + echo "Please update CHANGELOG.md with a new version before releasing" + exit 1 +fi + +NEW_VERSION="v$LATEST_VERSION" +MAJOR_VERSION=$(echo $LATEST_VERSION | cut -d. -f1) + +echo -e "${GREEN}Releasing version: $NEW_VERSION${NC}" + +# Create and push the exact version tag +echo "Creating tag $NEW_VERSION..." +git tag -a "$NEW_VERSION" -m "Release $NEW_VERSION" + +# Update the major version tag (floating tag) +echo "Updating floating tag v$MAJOR_VERSION..." +git tag -fa "v$MAJOR_VERSION" -m "Update v$MAJOR_VERSION to $NEW_VERSION" + +# Push tags +echo "Pushing tags..." +git push origin "$NEW_VERSION" +git push -f origin "v$MAJOR_VERSION" + +echo -e "${GREEN}โœ… Release complete!${NC}" +echo "" +echo "Tagged and pushed:" +echo " - $NEW_VERSION (exact version)" +echo " - v$MAJOR_VERSION (floating tag)" +echo "" +echo "Users can now use:" +echo " - lukemun/context-ledger@$NEW_VERSION (pinned)" +echo " - lukemun/context-ledger@v$MAJOR_VERSION (auto-updates)" From bf22f5e5e954d165a6e3981b99b8734ffa865a6e Mon Sep 17 00:00:00 2001 From: lukemun Date: Fri, 15 Aug 2025 13:47:13 -0400 Subject: [PATCH 2/4] refactor: simplify to dual workflow approach - Remove complex integration tests - Rename changelog-test to changelog-local for clarity - Add workflow source comments to distinguish runs - Update README with clearer dual workflow explanation Now simply: - changelog.yml uses published @v1 (production) - changelog-local.yml uses ./ (test PR changes) --- .github/workflows/changelog-local.yml | 68 +++++++++++++++++++ .github/workflows/changelog-test.yml | 61 ----------------- .github/workflows/changelog.yml | 26 +++++++ .github/workflows/integration-test.yml | 94 -------------------------- README.md | 16 +++-- 5 files changed, 105 insertions(+), 160 deletions(-) create mode 100644 .github/workflows/changelog-local.yml delete mode 100644 .github/workflows/changelog-test.yml delete mode 100644 .github/workflows/integration-test.yml diff --git a/.github/workflows/changelog-local.yml b/.github/workflows/changelog-local.yml new file mode 100644 index 0000000..560e7f4 --- /dev/null +++ b/.github/workflows/changelog-local.yml @@ -0,0 +1,68 @@ +name: Update Changelog (Local Version) + +# This workflow uses the local version of Context Ledger from the PR +# Useful for testing changes before they're published + +on: + pull_request: + branches: [main] + types: [opened, synchronize, reopened, ready_for_review] + paths-ignore: + - "docs/**" + - "**/CHANGELOG.md" + - "CHANGELOG.md" + + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + issues: write + +jobs: + update-changelog-local: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Update Changelog with Local Context Ledger + uses: ./ # Uses the local action code from this PR + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + changelog_path: "CHANGELOG.md" + target_name: "context-ledger" + version_increment: "auto" + auto_commit: ${{ github.event_name != 'pull_request' }} + create_pr_suggestions: ${{ github.event_name == 'pull_request' }} + continue-on-error: true + + - name: Add workflow source comment + if: github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + // Only comment once per PR + const comments = await github.rest.issues.listComments({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo + }); + + const hasComment = comments.data.some(c => + c.body.includes('๐Ÿงช Workflow: Local Version') + ); + + if (!hasComment) { + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: '๐Ÿงช **Workflow: Local Version** - This changelog was generated using the PR\'s local code (`./`)' + }); + } diff --git a/.github/workflows/changelog-test.yml b/.github/workflows/changelog-test.yml deleted file mode 100644 index 8e81107..0000000 --- a/.github/workflows/changelog-test.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: Test Changelog (PR Version) - -# This workflow tests the PR version of the action against itself -# It only runs when action code is modified - -on: - pull_request: - branches: [main] - types: [opened, synchronize, reopened, ready_for_review] - paths: - - "action.yml" - - "lib/**" - - "package.json" - - ".github/workflows/changelog-test.yml" - -permissions: - contents: write - pull-requests: write - issues: write - -jobs: - test-pr-version: - runs-on: ubuntu-latest - name: Test PR Version - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.ref }} - fetch-depth: 0 - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Test Changelog with PR Version - uses: ./ # Uses the local action code from this PR - with: - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - changelog_path: "CHANGELOG.md" - target_name: "context-ledger-test" - version_increment: "auto" - auto_commit: false # Never auto-commit in test mode - create_pr_suggestions: true - continue-on-error: true - - - name: Report Test Status - if: always() - uses: actions/github-script@v7 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const status = '${{ steps.test-changelog.outcome }}'; - const body = status === 'success' - ? 'โœ… **Test Passed**: PR version of Context Ledger ran successfully!' - : 'โš ๏ธ **Test Status**: PR version completed with status: ' + status; - - // Post a comment with test results - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: body + '\n\n*This is a test run using the PR version of the action.*' - }); diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index f6b2248..ae157e6 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -51,3 +51,29 @@ jobs: auto_commit: ${{ github.event_name != 'pull_request' }} create_pr_suggestions: ${{ github.event_name == 'pull_request' }} continue-on-error: true # Allow PR to succeed even if API key is missing + + - name: Add workflow source comment + if: github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + // Only comment once per PR + const comments = await github.rest.issues.listComments({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo + }); + + const hasComment = comments.data.some(c => + c.body.includes('๐Ÿท๏ธ Workflow: Production Version') + ); + + if (!hasComment) { + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: '๐Ÿท๏ธ **Workflow: Production Version** - This changelog was generated using `lukemun/context-ledger@v1`' + }); + } diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml deleted file mode 100644 index 4110c5b..0000000 --- a/.github/workflows/integration-test.yml +++ /dev/null @@ -1,94 +0,0 @@ -name: Integration Tests - -on: - pull_request: - branches: [main] - paths: - - "action.yml" - - "lib/**" - - "package.json" - workflow_dispatch: - -jobs: - test-scenarios: - runs-on: ubuntu-latest - strategy: - matrix: - test-case: - - name: "Empty Changelog" - changelog: | - # Changelog - - - - name: "Existing Versions" - changelog: | - # Changelog - - ## [1.0.0] - 2024-01-01 - - Initial release - - - - name: "Multiple Markers" - changelog: | - # Changelog - - ## [1.0.0] - - - ## [0.9.0] - - - name: "No Marker" - changelog: | - # Changelog - - ## [1.0.0] - 2024-01-01 - - Initial release - - name: Test - ${{ matrix.test-case.name }} - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.ref }} - fetch-depth: 0 - - - name: Create test changelog - run: | - cat > test-CHANGELOG.md << 'EOF' - ${{ matrix.test-case.changelog }} - EOF - - - name: Run Context Ledger - id: changelog - uses: ./ - with: - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - changelog_path: "test-CHANGELOG.md" - target_name: "test-${{ matrix.test-case.name }}" - version_increment: "patch" - auto_commit: false - create_pr_suggestions: false - continue-on-error: true - - - name: Validate Results - run: | - echo "Test Case: ${{ matrix.test-case.name }}" - echo "Status: ${{ steps.changelog.outputs.status }}" - echo "Updated: ${{ steps.changelog.outputs.changelog_updated }}" - echo "Version: ${{ steps.changelog.outputs.version_generated }}" - - # Show the resulting changelog - echo "=== Resulting Changelog ===" - cat test-CHANGELOG.md || echo "File not found" - - # Basic validation - if [ "${{ matrix.test-case.name }}" == "No Marker" ]; then - if [ "${{ steps.changelog.outputs.status }}" != "ERROR" ]; then - echo "โŒ Expected ERROR for no marker case" - exit 1 - fi - fi - - - name: Cleanup - if: always() - run: rm -f test-CHANGELOG.md diff --git a/README.md b/README.md index c90be5d..d9373a4 100644 --- a/README.md +++ b/README.md @@ -432,13 +432,19 @@ act pull_request -s ANTHROPIC_API_KEY=your_test_key ## ๐Ÿงช Testing & Development -### Testing Strategy +### Dual Workflow Approach -Context Ledger uses a dual-workflow testing approach: +Context Ledger provides two workflows for maximum flexibility: -1. **Production Testing** (`changelog.yml`): Uses the published version (`@v1`) -2. **PR Testing** (`changelog-test.yml`): Tests PR changes using local code (`./`) -3. **Integration Tests** (`integration-test.yml`): Matrix tests for edge cases +1. **Production Workflow** (`changelog.yml`) - Uses the published version (`@v1`) + - Stable, tested version + - What your users will experience + - Runs automatically on PRs and releases + +2. **Local Workflow** (`changelog-local.yml`) - Uses the PR's code (`./`) + - Test changes before merging + - Verify fixes work as expected + - Same functionality, different source ### Release Process From 2bac75589b8bc784c403662a4444451e64310ace Mon Sep 17 00:00:00 2001 From: lukemun Date: Fri, 15 Aug 2025 13:51:01 -0400 Subject: [PATCH 3/4] refactor: improve workflow names for clarity - Rename 'Test Claude Changelog Action' to 'Test Action' - Add descriptive job names: - 'Validate Action Structure' for test-action - 'Lint and Syntax Check' for lint-and-validate - 'Manual Integration Test' for integration-test This makes the GitHub Actions UI clearer and more consistent --- .github/workflows/test.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b017fd0..86f3b09 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,4 +1,4 @@ -name: Test Claude Changelog Action +name: Test Action on: push: @@ -9,6 +9,7 @@ on: jobs: test-action: + name: Validate Action Structure runs-on: ubuntu-latest permissions: contents: write @@ -58,6 +59,7 @@ jobs: echo "โœ… Script structure validation passed" lint-and-validate: + name: Lint and Syntax Check runs-on: ubuntu-latest steps: @@ -104,6 +106,7 @@ jobs: echo "โœ… JavaScript syntax is valid" integration-test: + name: Manual Integration Test runs-on: ubuntu-latest if: github.event_name == 'workflow_dispatch' permissions: From 2a19b1ed2420b32c708fc7f1c8db9a16a760cab7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 17:51:45 +0000 Subject: [PATCH 4/4] chore: prepare changelog for AI suggestions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ๐Ÿค– Automated by Claude AI [skip ci] --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8835178..707e757 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,3 +38,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Provides detailed outputs for integration with other workflows + +