diff --git a/.github/workflows/create-release-pr.yml b/.github/workflows/create-release-pr.yml index a0100434..78bdc5f5 100644 --- a/.github/workflows/create-release-pr.yml +++ b/.github/workflows/create-release-pr.yml @@ -8,14 +8,13 @@ on: default: 'vx.x.x' required: true type: string - pre_release_version: - description: "(Optional) Pre-Release version, e.g. 'b1'. Used mainly to support consensus release on betanet." - required: false + base_branch: + description: "The base branch to release from; only override this if preparing a release off of the non-default branch" + default: 'main' + required: true type: string - env: RELEASE_VERSION: ${{ inputs.release_version }} - PRE_RELEASE_VERSION: ${{ inputs.pre_release_version }} RELEASE_BRANCH: release/${{ inputs.release_version }} jobs: @@ -27,25 +26,18 @@ jobs: id: set-release run: | if [[ $RELEASE_VERSION =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - if [[ $PRE_RELEASE_VERSION =~ ^[a-z.0-9]+$ ]]; then - echo "release-tag: $RELEASE_VERSION$PRE_RELEASE_VERSION" - echo "release-tag=$RELEASE_VERSION$PRE_RELEASE_VERSION" >> $GITHUB_OUTPUT - elif [[ -n $PRE_RELEASE_VERSION ]]; then - echo "Input pre_release_version is not empty, but does not match the regex pattern ^[a-z.0-9]+$" - exit 1 - else - echo "release-tag: $RELEASE_VERSION" - echo "release-tag=$RELEASE_VERSION" >> $GITHUB_OUTPUT - fi + echo "release-tag: $RELEASE_VERSION" + echo "release-tag=$RELEASE_VERSION" >> $GITHUB_OUTPUT else - echo "Version input doesn't match the regex pattern ^v[0-9]+\.[0-9]+\.[0-9]+$" + echo "Version input doesn't match the regex pattern ^[0-9]+\.[0-9]+\.[0-9]+$" exit 1 fi - name: Checkout - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4 with: fetch-depth: 0 + ref: ${{ inputs.base_branch }} - name: Create Release Branch if it does not exist run: | @@ -63,24 +55,18 @@ jobs: - name: Get Latest Release id: get-release run: | - if [[ -n $PRE_RELEASE_VERSION ]]; then - echo "Get the latest release" - tag=$(curl -L \ - --header "Accept: application/vnd.github.v3+json" \ - "https://api.github.com/repos/${{ github.repository }}/releases" | jq -r '.[0].tag_name') - echo "latest-tag=$tag" >> $GITHUB_OUTPUT - else - echo "Get the latest stable release" - tag=$(curl -L \ - --header "Accept: application/vnd.github.v3+json" \ - "https://api.github.com/repos/${{ github.repository }}/releases/latest" | jq -r '.tag_name') - echo "latest-tag=$tag" >> $GITHUB_OUTPUT - fi + echo "Get the latest stable release" + tag=$(curl -L \ + --header "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/${{ github.repository }}/releases/latest" | jq -r '.tag_name') + echo "latest-tag=$tag" >> $GITHUB_OUTPUT + - name: Build Changelog id: build-changelog env: PREVIOUS_VERSION: ${{ steps.get-release.outputs.latest-tag }} + RELEASE_TAG: ${{ steps.set-release.outputs.release-tag }} run: | CHANGELOG=$(curl -L \ -X POST \ @@ -99,7 +85,6 @@ jobs: echo "$EOF" >> $GITHUB_OUTPUT - name: Update Changelog - if: ${{ env.PRE_RELEASE_VERSION == '' }} env: CHANGELOG_CONTENT: ${{ steps.build-changelog.outputs.changelog }} PREVIOUS_VERSION: ${{ steps.get-release.outputs.latest-tag }} @@ -120,47 +105,24 @@ jobs: with: message: "bump up version to ${{ env.RELEASE_TAG }}" - - name: Create Pull Request to Master + - name: Create Pull Request to ${{ inputs.base_branch }} env: CHANGELOG_CONTENT: ${{ steps.build-changelog.outputs.changelog }} PREVIOUS_VERSION: ${{ steps.get-release.outputs.latest-tag }} GH_TOKEN: ${{ github.token }} RELEASE_TAG: ${{ steps.set-release.outputs.release-tag }} run: | - # Note: There's an issue adding teams as reviewers, see https://github.com/cli/cli/issues/6395 - PULL_REQUEST_URL=$(gh pr create --base "master" \ - --title "FOR REVIEW ONLY: ${{ github.event.repository.name }} $RELEASE_TAG" \ + PULL_REQUEST_URL=$(gh pr create --base "${{ inputs.base_branch }}" \ + --title "FOR REVIEW ONLY: ${{ github.event.repository.name }} $RELEASE_TAG changelog and version bump" \ --label "Skip-Release-Notes" \ - --label "Team Hyper Flow" \ --body "${CHANGELOG_CONTENT}" | tail -n 1) if [[ $PULL_REQUEST_URL =~ ^https://github.com/${{ github.repository }}/pull/[0-9]+$ ]]; then PULL_REQUEST_NUM=$(echo $PULL_REQUEST_URL | sed 's:.*/::') - echo "pull-request-master=$PULL_REQUEST_URL" >> $GITHUB_ENV - echo "pull-request-master-num=$PULL_REQUEST_NUM" >> $GITHUB_ENV - echo "Pull request to Master created: $PULL_REQUEST_URL" - else - echo "There was an issue creating the pull request to master branch." - exit 1 - fi - - - name: Create Pull Request to Develop - if: ${{ env.PRE_RELEASE_VERSION == '' }} - env: - GH_TOKEN: ${{ github.token }} - RELEASE_TAG: ${{ steps.set-release.outputs.release-tag }} - run: | - # Note: There's an issue adding teams as reviewers, see https://github.com/cli/cli/issues/6395 - PULL_REQUEST_URL=$(gh pr create --base "develop" \ - --title "FOR REVIEW ONLY: Merge back ${{ github.event.repository.name }} $RELEASE_TAG to develop" \ - --label "Skip-Release-Notes" \ - --label "Team Hyper Flow" \ - --body "Merge back version changes to develop." | tail -n 1) - if [[ $PULL_REQUEST_URL =~ ^https://github.com/${{ github.repository }}/pull/[0-9]+$ ]]; then - echo "Pull request to Develop created: $PULL_REQUEST_URL" - DEVELOP_PR_MESSAGE="\nPull Request to develop: $PULL_REQUEST_URL" - echo "pull-request-develop-message=$DEVELOP_PR_MESSAGE" >> $GITHUB_ENV + echo "pull-request-base-branch=$PULL_REQUEST_URL" >> $GITHUB_ENV + echo "pull-request-base-branch-num=$PULL_REQUEST_NUM" >> $GITHUB_ENV + echo "Pull request to ${{ inputs.base_branch }} created: $PULL_REQUEST_URL" else - echo "There was an issue creating the pull request to develop branch." + echo "There was an issue creating the pull request to ${{ inputs.base_branch }} branch." exit 1 fi @@ -171,7 +133,7 @@ jobs: RELEASE_TAG: ${{ steps.set-release.outputs.release-tag }} SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK - SDK_DEPLOYMENT_URL: ${{ secrets.SDK_DEPLOYMENT_URL }} + RELEASE_WORKFLOW: "workflows/release.yml" with: payload: | { @@ -187,14 +149,14 @@ jobs: "type": "section", "text": { "type": "mrkdwn", - "text": "*Approvals needed for*:\nPull Request to master: ${{ env.pull-request-master}}${{ env.pull-request-develop-message }}" + "text": "*Approval needed for*:\nPull Request to ${{ inputs.base_branch }}: ${{ env.pull-request-base-branch}}" } }, { "type": "section", "text": { "type": "mrkdwn", - "text": "*After approvals*\nDeploy SDK using the <${{ env.SDK_DEPLOYMENT_URL }}|Deployment Pipeline> with the following parameters:\n*SDK*: ${{ github.event.repository.name }}\n*RELEASE_PR_NUM*: ${{ env.pull-request-master-num }}\n*RELEASE_VERSION*: ${{ env.RELEASE_VERSION }}\n*PRE_RELEASE_VERSION*: ${{ env.PRE_RELEASE_VERSION }}" + "text": "*After approval*\nRelease and Deploy SDK using the <${{ env.RELEASE_WORKFLOW }}> with the following parameters:\n*release_pr_number*: ${{ env.pull-request-base-branch-num }}\n*release_version*: ${{ env.RELEASE_VERSION }}" } } ] diff --git a/.github/workflows/pr-type-category.yml b/.github/workflows/pr-type-category.yml index c33fce94..09864f50 100644 --- a/.github/workflows/pr-type-category.yml +++ b/.github/workflows/pr-type-category.yml @@ -2,7 +2,7 @@ name: Check PR category and type on: pull_request: branches: - - develop + - main types: [opened, synchronize, reopened, labeled, unlabeled, edited] jobs: check_label: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000..5ca6fecb --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,62 @@ +name: "Publish Python package to PyPI" + +on: + workflow_dispatch: + inputs: + tag_version: + description: 'The tag_version, e.g. vx.x.x' + default: 'vx.x.x' + required: true + type: 'string' + python_version: + description: 'The Python version to build with.' + default: '3.10' + required: true + type: 'string' + dry_run: + description: 'Whether this is a dry_run publish.' + default: 'true' + required: true + type: 'boolean' + +jobs: + build_and_publish: + runs-on: ubuntu-24.04 + permissions: + contents: read + id-token: write + steps: + # Checkout the repository at the specified tag version + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.tag_version }} + + # Set up Python environment + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: ${{ inputs.python_version }} + + # Install required tools for building and publishing the package + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build twine + + # Build the package + - name: Build the package + run: python -m build + + # Publish to PyPI + - name: Publish to PyPI + run: | + echo 'DRY_RUN: '$DRY_RUN + if [ "$DRY_RUN" == "false" ]; then + twine upload dist/* + else + twine upload --repository testpypi dist/* + fi + env: + TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + DRY_RUN: ${{ inputs.dry_run }} \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..136367db --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,162 @@ +name: "Create and Publish Release" + +on: + workflow_dispatch: + inputs: + release_pr_number: + description: "The pull request number to merge that contains the package version bumps and changelog updates." + required: true + type: number + release_version: + description: "The tag name for the release (e.g., v1.2.3)" + required: true + type: string + dry_run: + description: "Set to true to 'dry-run'/not actually publish to PyPI." + default: "true" + required: true + type: boolean + python_version: + description: 'The Python version to build with.' + default: '3.10' + required: true + type: 'string' + +jobs: + release_and_publish: + runs-on: ubuntu-24.04 + permissions: + contents: write # Needed for creating releases and tags, and deleting branches + pull-requests: write # Needed for merging the PR + steps: + - name: Get Pull Request Info (Base Branch, Release Notes) + id: get_pr_info + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const prNumber = parseInt(process.env.RELEASE_PR_NUMBER, 10); + const result = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + }); + + core.setOutput('RELEASE_NOTES', result.data.body); + core.setOutput('RELEASE_TAG', process.env.RELEASE_VERSION); + core.setOutput('BASE_BRANCH', result.data.base.ref); // Capture base branch + env: + RELEASE_PR_NUMBER: ${{ github.event.inputs.release_pr_number }} + RELEASE_VERSION: ${{ github.event.inputs.release_version }} + + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ steps.get_pr_info.outputs.BASE_BRANCH }} + fetch-depth: 0 + + - name: Set up Git + run: | + git config --local user.name "GitHub Actions" + git config --local user.email "actions@github.com" + + - name: Merge Pull Request + uses: actions/github-script@v7 + id: merge_pr + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const prNumber = parseInt('${{ github.event.inputs.release_pr_number }}', 10); + const result = await github.rest.pulls.merge({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + }); + + core.setOutput('merged', result.data.merged); + + - name: Ensure latest changes from merged PR + run: | + git fetch origin ${{ steps.get_pr_info.outputs.BASE_BRANCH }} + git reset --hard origin/${{ steps.get_pr_info.outputs.BASE_BRANCH }} + + - name: Create Release + uses: softprops/action-gh-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.event.inputs.release_version }} + name: ${{ github.event.inputs.release_version }} + body: ${{ steps.get_pr_info.outputs.RELEASE_NOTES }} + generate_release_notes: false + + # Set up Python environment + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: ${{ inputs.python_version }} + + # Install required tools for building and publishing the package + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build twine + + # Build the package + - name: Build the package + run: python -m build + + # Publish to PyPI + - name: Publish to PyPI + run: | + echo 'DRY_RUN: '$DRY_RUN + if [ "$DRY_RUN" == "false" ]; then + twine upload dist/* + else + twine upload --repository testpypi dist/* + fi + env: + TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + DRY_RUN: ${{ inputs.dry_run }} + + - name: Delete branch after merge + if: steps.merge_pr.outputs.merged == 'true' # Only delete if merge was successful + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const branchName = `release/${{ github.event.inputs.release_version }}`; + + try { + await github.rest.git.deleteRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: `heads/${branchName}`, + }); + console.log(`Successfully deleted branch: ${branchName}`); + } catch (error) { + console.error(`Failed to delete branch ${branchName}:`, error); + } + + - name: Notify Slack - Release Completed + id: slack-release + uses: slackapi/slack-github-action@v1.27.1 + env: + SDK: ${{ github.event.repository.name }} + RELEASE_TAG: ${{ steps.get_pr_info.outputs.RELEASE_TAG }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_RELEASE_NOTIFICATIONS_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK + with: + payload: | + { + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "*${{ env.SDK }} ${{ env.RELEASE_TAG }}* was released today. https://github.com/${{ github.repository }}/releases/tag/${{ env.RELEASE_TAG }}" + } + } + ] + } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index e49af153..33cf7599 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ # Changelog +# v2.10.0 + + + +## What's Changed +### Enhancements +* Introduce publishing/releasing entirely through github actions. by @gmalouf in https://github.com/gmalouf/py-algorand-sdk/pull/1 +* Set testpypi repo. by @gmalouf in https://github.com/gmalouf/py-algorand-sdk/pull/3 + +## New Contributors +* @gmalouf made their first contribution in https://github.com/gmalouf/py-algorand-sdk/pull/1 +* @github-actions made their first contribution in https://github.com/gmalouf/py-algorand-sdk/pull/6 + +**Full Changelog**: https://github.com/gmalouf/py-algorand-sdk/compare/v2.8.0...v2.10.0 + +# v2.9.0 + + + +## What's Changed +### Enhancements +* Introduce publishing/releasing entirely through github actions. by @gmalouf in https://github.com/gmalouf/py-algorand-sdk/pull/1 +* Set testpypi repo. by @gmalouf in https://github.com/gmalouf/py-algorand-sdk/pull/3 + +## New Contributors +* @gmalouf made their first contribution in https://github.com/gmalouf/py-algorand-sdk/pull/1 + +**Full Changelog**: https://github.com/gmalouf/py-algorand-sdk/compare/v2.8.0...v2.9.0 + # v2.8.0 diff --git a/setup.py b/setup.py index cf3d4f1f..eafcbdd7 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ description="Algorand SDK in Python", author="Algorand", author_email="pypiservice@algorand.com", - version="2.8.0", + version="2.10.0", long_description=long_description, long_description_content_type="text/markdown", url="https://github.com/algorand/py-algorand-sdk",