changelogs 0.0.1

Manage versioning and changelogs for Cargo workspaces
Documentation
name: 'Changelogs'
description: 'Create a PR with version bumps and changelogs, and publish packages when merged'
author: 'wevm'

branding:
  icon: 'package'
  color: 'orange'

inputs:
  version:
    description: 'Command to run for versioning'
    required: false
    default: 'changelogs version'
  publish:
    description: 'Command to run for publishing (runs when no changelogs are pending)'
    required: false
  crate-token:
    description: 'Crates.io API token for publishing'
    required: false
  commit:
    description: 'Commit message for version bump'
    required: false
    default: 'Version Packages'
  title:
    description: 'Pull request title'
    required: false
    default: 'Version Packages'
  branch:
    description: 'Branch name for the version PR'
    required: false
    default: 'changelog-release/main'
  github-token:
    description: 'GitHub token for creating PRs'
    required: false
    default: ${{ github.token }}

outputs:
  hasChangelogs:
    description: 'Whether there are pending changelogs'
    value: ${{ steps.check.outputs.hasChangelogs }}
  pullRequestNumber:
    description: 'The pull request number if created or updated'
    value: ${{ steps.pr.outputs.pull-request-number }}
  published:
    description: 'Whether packages were published'
    value: ${{ steps.publish.outputs.published }}
  publishedPackages:
    description: 'JSON array of published packages'
    value: ${{ steps.publish.outputs.publishedPackages }}

runs:
  using: 'composite'
  steps:
    - name: Check for changelogs
      id: check
      shell: bash
      run: |
        if [ -d ".changelog" ] && [ "$(find .changelog -name '*.md' ! -name 'README.md' 2>/dev/null | head -1)" ]; then
          echo "hasChangelogs=true" >> $GITHUB_OUTPUT
          echo "Found pending changelogs"
        else
          echo "hasChangelogs=false" >> $GITHUB_OUTPUT
          echo "No pending changelogs"
        fi

    # Version mode: Create PR when changelogs exist
    - name: Setup Git user
      if: steps.check.outputs.hasChangelogs == 'true'
      shell: bash
      run: |
        git config user.name "github-actions[bot]"
        git config user.email "41898282+github-actions[bot]@users.noreply.github.com"

    - name: Run version command
      if: steps.check.outputs.hasChangelogs == 'true'
      shell: bash
      run: ${{ inputs.version }}

    - name: Generate PR body
      if: steps.check.outputs.hasChangelogs == 'true'
      id: body
      shell: bash
      run: |
        EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
        echo "body<<$EOF" >> $GITHUB_OUTPUT
        echo "This PR was opened by the Changelogs release workflow." >> $GITHUB_OUTPUT
        echo "" >> $GITHUB_OUTPUT
        echo "When you're ready to release, merge this PR and the packages will be published." >> $GITHUB_OUTPUT
        echo "" >> $GITHUB_OUTPUT
        echo "---" >> $GITHUB_OUTPUT
        echo "" >> $GITHUB_OUTPUT
        
        # Include changelog content
        if [ -f "CHANGELOG.md" ]; then
          tail -n +3 "CHANGELOG.md" | head -100 >> $GITHUB_OUTPUT
        fi
        
        echo "$EOF" >> $GITHUB_OUTPUT

    - name: Create or update PR
      if: steps.check.outputs.hasChangelogs == 'true'
      id: pr
      uses: peter-evans/create-pull-request@v7
      with:
        token: ${{ inputs.github-token }}
        branch: ${{ inputs.branch }}
        title: ${{ inputs.title }}
        body: ${{ steps.body.outputs.body }}
        base: ${{ github.ref_name }}
        commit-message: ${{ inputs.commit }}
        delete-branch: true

    # Publish mode: Publish when no changelogs (PR was just merged)
    - name: Publish packages
      if: steps.check.outputs.hasChangelogs == 'false' && inputs.publish != ''
      id: publish
      shell: bash
      env:
        CARGO_REGISTRY_TOKEN: ${{ inputs.crate-token }}
      run: |
        echo "Running publish command: ${{ inputs.publish }}"
        output=$(${{ inputs.publish }} 2>&1) || true
        echo "$output"
        
        # Parse published packages from output
        packages=$(echo "$output" | grep -E "^\s+\S+\s+v[0-9]" | grep "✓" | awk '{print $1}' | jq -R -s -c 'split("\n") | map(select(length > 0))')
        
        if [ "$packages" != "[]" ] && [ -n "$packages" ]; then
          echo "published=true" >> $GITHUB_OUTPUT
          echo "publishedPackages=$packages" >> $GITHUB_OUTPUT
        else
          echo "published=false" >> $GITHUB_OUTPUT
          echo "publishedPackages=[]" >> $GITHUB_OUTPUT
        fi

    - name: Push git tags
      if: steps.check.outputs.hasChangelogs == 'false' && inputs.publish != '' && steps.publish.outputs.published == 'true'
      shell: bash
      run: git push --follow-tags