Prepare Release #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Prepare Release | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Release version (e.g., 0.40.0)' | |
| required: true | |
| type: string | |
| dry_run: | |
| description: 'Dry run mode (just show what would happen)' | |
| required: true | |
| type: boolean | |
| default: true | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| jobs: | |
| prepare-release: | |
| runs-on: ubuntu-latest | |
| environment: release | |
| steps: | |
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
| - name: Validate inputs | |
| run: | | |
| # Validate version format | |
| if [[ ! "${{ inputs.version }}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "Error: Version must be in format X.Y.Z (e.g., 0.40.0)" | |
| exit 1 | |
| fi | |
| # Check if repository is clean | |
| if [ -n "$(git status --porcelain)" ]; then | |
| echo "Error: Repository has uncommitted changes" | |
| git status | |
| exit 1 | |
| fi | |
| - name: Get last released version | |
| id: last_version | |
| run: | | |
| # Get the latest tag | |
| LAST_TAG=$(git tag --list 'v*' --sort=-version:refname | head -n1) | |
| if [ -z "$LAST_TAG" ]; then | |
| echo "No previous tags found" | |
| LAST_VERSION="0.0.0" | |
| else | |
| LAST_VERSION=${LAST_TAG#v} | |
| fi | |
| echo "last_version=$LAST_VERSION" >> $GITHUB_OUTPUT | |
| echo "Last released version: $LAST_VERSION" | |
| echo "New version: ${{ inputs.version }}" | |
| - name: Validate version increment | |
| run: | | |
| LAST_VERSION="${{ steps.last_version.outputs.last_version }}" | |
| NEW_VERSION="${{ inputs.version }}" | |
| # Simple version comparison (assumes semantic versioning) | |
| if [ "$LAST_VERSION" != "0.0.0" ]; then | |
| if ! printf '%s\n%s\n' "$LAST_VERSION" "$NEW_VERSION" | sort -V -C; then | |
| echo "Error: New version $NEW_VERSION is not greater than last version $LAST_VERSION" | |
| exit 1 | |
| fi | |
| fi | |
| - name: Extract changelog content | |
| id: changelog | |
| run: | | |
| # Extract content from ## Unreleased section | |
| if [ ! -f "CHANGELOG.md" ]; then | |
| echo "Error: CHANGELOG.md not found" | |
| exit 1 | |
| fi | |
| # Get unreleased content | |
| UNRELEASED_CONTENT=$(awk '/^## Unreleased/,/^## \[/ { | |
| if (/^## Unreleased/) next | |
| if (/^## \[/) exit | |
| }' CHANGELOG.md | sed '/^$/d') | |
| if [ -z "$UNRELEASED_CONTENT" ]; then | |
| echo "Error: No unreleased content found in CHANGELOG.md" | |
| exit 1 | |
| fi | |
| # Save to file for later use | |
| echo "$UNRELEASED_CONTENT" > /tmp/changelog_content.txt | |
| echo "Found changelog content:" | |
| cat /tmp/changelog_content.txt | |
| - name: Update CHANGELOG.md | |
| run: | | |
| # Create new changelog with release section | |
| RELEASE_DATE=$(date -u +"%Y-%m-%d") | |
| NEW_VERSION="${{ inputs.version }}" | |
| # Create temporary file with new content | |
| { | |
| # Keep everything up to ## Unreleased | |
| awk '/^## Unreleased/ {print; exit}' CHANGELOG.md | |
| echo "" | |
| # Add new release section | |
| echo "## [${NEW_VERSION}](https://github.com/open-telemetry/otel-arrow/releases/tag/v${NEW_VERSION}) - ${RELEASE_DATE}" | |
| echo "" | |
| # Add unreleased content | |
| cat /tmp/changelog_content.txt | |
| echo "" | |
| # Add rest of changelog (starting from first existing release) | |
| awk '/^## \[.*\]/ {found=1} found {print}' CHANGELOG.md | |
| } > CHANGELOG.md.tmp | |
| mv CHANGELOG.md.tmp CHANGELOG.md | |
| echo "Updated CHANGELOG.md with release $NEW_VERSION" | |
| - name: Dry run - Show planned changes | |
| if: inputs.dry_run | |
| run: | | |
| echo "=== DRY RUN MODE - No changes will be made ===" | |
| echo "" | |
| echo "Planned changes:" | |
| echo "- New version: ${{ inputs.version }}" | |
| echo "- Last version: ${{ steps.last_version.outputs.last_version }}" | |
| echo "" | |
| echo "Git diff:" | |
| git diff | |
| echo "" | |
| echo "Git operations that would occur:" | |
| echo " - Create branch: release-v${{ inputs.version }}" | |
| echo " - Commit version updates" | |
| echo " - Create pull request" | |
| echo "" | |
| echo "Note: After merging the PR, run the 'Push Release' workflow to create git tags and GitHub release" | |
| - name: Create GitHub App token | |
| if: '!inputs.dry_run' | |
| uses: actions/create-github-app-token@v1 | |
| id: app-token | |
| with: | |
| app-id: ${{ vars.OTELBOT_APP_ID }} | |
| private-key: ${{ secrets.OTELBOT_PRIVATE_KEY }} | |
| - name: Create release branch and commit changes | |
| if: '!inputs.dry_run' | |
| run: | | |
| # Configure git | |
| git config user.name otelbot | |
| git config user.email 197425009+otelbot@users.noreply.github.com | |
| # Create and switch to release branch | |
| git checkout -b "otelbot/release-v${{ inputs.version }}" | |
| # Add all changes | |
| git add . | |
| # Commit changes | |
| git commit -m "Prepare release v${{ inputs.version }} | |
| - Update CHANGELOG.md with release notes for v${{ inputs.version }} | |
| This commit prepares the repository for release v${{ inputs.version }}." | |
| # Push branch | |
| git push origin "otelbot/release-v${{ inputs.version }}" | |
| - name: Create pull request | |
| if: '!inputs.dry_run' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| # Create PR body content | |
| cat > /tmp/pr_body.md << 'EOF' | |
| ## Release v${{ inputs.version }} | |
| This PR prepares the repository for release v${{ inputs.version }}. | |
| ### Changes included: | |
| - Updated CHANGELOG.md with release notes | |
| ### Release Notes: | |
| ``` | |
| $(cat /tmp/changelog_content.txt) | |
| ``` | |
| ### Checklist: | |
| - [ ] Verify CHANGELOG.md formatting and content | |
| - [ ] Confirm all tests pass | |
| - [ ] Ready to merge and tag release | |
| After merging this PR, run the **Push Release** workflow to create git tags and publish the GitHub release. | |
| EOF | |
| # Create the pull request using GitHub CLI | |
| gh pr create \ | |
| --title "Release v${{ inputs.version }}" \ | |
| --body-file /tmp/pr_body.md \ | |
| --head "otelbot/release-v${{ inputs.version }}" \ | |
| --base main \ | |
| --label release | |
| - name: Summary | |
| run: | | |
| if [ "${{ inputs.dry_run }}" = "true" ]; then | |
| echo ":heavy_check_mark: Dry run completed successfully" | |
| echo "No changes were made to the repository" | |
| echo "Review the planned changes above and run again without dry-run when ready" | |
| else | |
| echo ":heavy_check_mark: Release preparation completed successfully" | |
| echo "" | |
| echo "Next steps:" | |
| echo "1. Review and merge the pull request: https://github.com/open-telemetry/otel-arrow/pulls" | |
| echo "2. After merging, run the 'Push Release' workflow to create git tags and GitHub release" | |
| echo "" | |
| echo "Release branch: otelbot/release-v${{ inputs.version }}" | |
| echo "Release version: v${{ inputs.version }}" | |
| fi |