diff --git a/.github/scripts/update-version.sh b/.github/scripts/update-version.sh new file mode 100755 index 000000000..0db3721b6 --- /dev/null +++ b/.github/scripts/update-version.sh @@ -0,0 +1,6 @@ +#!/bin/bash -e + +sed -i "/\[stable\]/{n;s/version=.*/version=$1/}" eachdist.ini +sed -i "/\[prerelease\]/{n;s/version=.*/version=$2/}" eachdist.ini + +./scripts/eachdist.py update_versions --versions stable,prerelease \ No newline at end of file diff --git a/.github/scripts/use-cla-approved-github-bot.sh b/.github/scripts/use-cla-approved-github-bot.sh new file mode 100755 index 000000000..a411c6812 --- /dev/null +++ b/.github/scripts/use-cla-approved-github-bot.sh @@ -0,0 +1,4 @@ +#!/bin/bash -e + +git config user.name opentelemetrybot +git config user.email 107717825+opentelemetrybot@users.noreply.github.com \ No newline at end of file diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 000000000..da0714ae1 --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,43 @@ +name: Backport +on: + workflow_dispatch: + inputs: + number: + description: "The pull request # to backport" + required: true + +jobs: + backport: + runs-on: ubuntu-latest + steps: + - run: | + if [[ ! $GITHUB_REF_NAME =~ ^release/v[0-9]+\.[0-9]+\.x-0\.[0-9]+bx$ ]]; then + echo this workflow should only be run against long-term release branches + exit 1 + fi + + - uses: actions/checkout@v3 + with: + # history is needed to run git cherry-pick below + fetch-depth: 0 + + - name: Use CLA approved github bot + run: .github/scripts/use-cla-approved-github-bot.sh + + - name: Create pull request + env: + NUMBER: ${{ github.event.inputs.number }} + # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows + GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} + run: | + commit=$(gh pr view $NUMBER --json mergeCommit --jq .mergeCommit.oid) + title=$(gh pr view $NUMBER --json title --jq .title) + + branch="opentelemetrybot/backport-${NUMBER}-to-${GITHUB_REF_NAME//\//-}" + + git cherry-pick $commit + git push origin HEAD:$branch + gh pr create --title "[$GITHUB_REF_NAME] $title" \ + --body "Clean cherry-pick of #$NUMBER to the \`$GITHUB_REF_NAME\` branch." \ + --head $branch \ + --base $GITHUB_REF_NAME \ No newline at end of file diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 11e1a61fc..5238e01c4 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -13,7 +13,9 @@ on: jobs: changelog: runs-on: ubuntu-latest - if: "!contains(github.event.pull_request.labels.*.name, 'Skip Changelog')" + if: | + !contains(github.event.pull_request.labels.*.name, 'Skip Changelog') + && github.actor != 'opentelemetrybot' steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/prepare-patch-release.yml b/.github/workflows/prepare-patch-release.yml new file mode 100644 index 000000000..93c4fc74f --- /dev/null +++ b/.github/workflows/prepare-patch-release.yml @@ -0,0 +1,82 @@ +name: Prepare patch release +on: + workflow_dispatch: + +jobs: + prepare-patch-release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - run: | + if [[ ! $GITHUB_REF_NAME =~ ^release/v[0-9]+\.[0-9]+\.x-0\.[0-9]+bx$ ]]; then + echo this workflow should only be run against long-term release branches + exit 1 + fi + + if ! grep --quiet "^## Unreleased$" CHANGELOG.md; then + echo the change log is missing an \"Unreleased\" section + exit 1 + fi + + - name: Set environment variables + run: | + stable_version=$(./scripts/eachdist.py version --mode stable) + unstable_version=$(./scripts/eachdist.py version --mode prerelease) + + if [[ $stable_version =~ ^([0-9]+\.[0-9]+)\.([0-9]+)$ ]]; then + stable_major_minor="${BASH_REMATCH[1]}" + stable_patch="${BASH_REMATCH[2]}" + else + echo "unexpected stable_version: $stable_version" + exit 1 + fi + + if [[ $unstable_version =~ ^0\.([0-9]+)b([0-9]+)$ ]]; then + unstable_minor="${BASH_REMATCH[1]}" + unstable_patch="${BASH_REMATCH[2]}" + else + echo "unexpected unstable_version: $unstable_version" + exit 1 + fi + + stable_version="$stable_major_minor.$((stable_patch + 1))" + unstable_version="0.${unstable_minor}b$((unstable_patch + 1))" + + echo "STABLE_VERSION=$stable_version" >> $GITHUB_ENV + echo "UNSTABLE_VERSION=$unstable_version" >> $GITHUB_ENV + + - name: Update version + run: .github/scripts/update-version.sh $STABLE_VERSION $UNSTABLE_VERSION + + - name: Set up Python 3.9 + uses: actions/setup-python@v2 + with: + python-version: 3.9 + - name: Install tox + run: pip install tox==3.27.1 + - name: run tox + run: tox -e generate + + - name: Update the change log with the approximate release date + run: | + date=$(date "+%Y-%m-%d") + sed -Ei "s/^## Unreleased$/## Version ${STABLE_VERSION}\/${UNSTABLE_VERSION} ($date)/" CHANGELOG.md + + - name: Use CLA approved github bot + run: .github/scripts/use-cla-approved-github-bot.sh + + - name: Create pull request + env: + # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows + GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} + run: | + message="Prepare release ${STABLE_VERSION}/${UNSTABLE_VERSION}" + branch="opentelemetrybot/prepare-release-${STABLE_VERSION}-${UNSTABLE_VERSION}" + + git commit -a -m "$message" + git push origin HEAD:$branch + gh pr create --title "[$GITHUB_REF_NAME] $message" \ + --body "$message." \ + --head $branch \ + --base $GITHUB_REF_NAME \ No newline at end of file diff --git a/.github/workflows/prepare-release-branch.yml b/.github/workflows/prepare-release-branch.yml new file mode 100644 index 000000000..f8edb3bef --- /dev/null +++ b/.github/workflows/prepare-release-branch.yml @@ -0,0 +1,195 @@ +name: Prepare release branch +on: + workflow_dispatch: + inputs: + prerelease_version: + description: "Pre-release version number? (e.g. 1.9.0rc2)" + required: false + +jobs: + prereqs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Verify prerequisites + env: + PRERELEASE_VERSION: ${{ github.event.inputs.prerelease_version }} + run: | + if [[ $GITHUB_REF_NAME != main ]]; then + echo this workflow should only be run against main + exit 1 + fi + + if ! grep --quiet "^## Unreleased$" CHANGELOG.md; then + echo the change log is missing an \"Unreleased\" section + exit 1 + fi + + if [[ ! -z $PRERELEASE_VERSION ]]; then + stable_version=$(./scripts/eachdist.py version --mode stable) + stable_version=${stable_version//.dev/} + if [[ $PRERELEASE_VERSION != ${stable_version}* ]]; then + echo "$PRERELEASE_VERSION is not a prerelease for the version on main ($stable_version)" + exit 1 + fi + fi + + create-pull-request-against-release-branch: + runs-on: ubuntu-latest + needs: prereqs + steps: + - uses: actions/checkout@v3 + + - name: Create release branch + env: + PRERELEASE_VERSION: ${{ github.event.inputs.prerelease_version }} + run: | + if [[ -z $PRERELEASE_VERSION ]]; then + stable_version=$(./scripts/eachdist.py version --mode stable) + stable_version=${stable_version//.dev/} + else + stable_version=$PRERELEASE_VERSION + fi + + unstable_version=$(./scripts/eachdist.py version --mode prerelease) + unstable_version=${unstable_version//.dev/} + + if [[ $stable_version =~ ^([0-9]+)\.([0-9]+)\.0$ ]]; then + stable_version_branch_part=$(echo $stable_version | sed -E 's/([0-9]+)\.([0-9]+)\.0/\1.\2.x/') + unstable_version_branch_part=$(echo $unstable_version | sed -E 's/0\.([0-9]+)b0/0.\1bx/') + release_branch_name="release/v${stable_version_branch_part}-${unstable_version_branch_part}" + elif [[ $stable_version =~ ^([0-9]+)\.([0-9]+)\.0 ]]; then + # pre-release version, e.g. 1.9.0rc2 + release_branch_name="release/v$stable_version-$unstable_version" + else + echo "unexpected version: $stable_version" + exit 1 + fi + + git push origin HEAD:$release_branch_name + + echo "STABLE_VERSION=$stable_version" >> $GITHUB_ENV + echo "UNSTABLE_VERSION=$unstable_version" >> $GITHUB_ENV + echo "RELEASE_BRANCH_NAME=$release_branch_name" >> $GITHUB_ENV + + - name: Update version + run: .github/scripts/update-version.sh $STABLE_VERSION $UNSTABLE_VERSION + + - name: Set up Python 3.9 + uses: actions/setup-python@v2 + with: + python-version: 3.9 + - name: Install tox + run: pip install tox==3.27.1 + - name: run tox + run: tox -e generate + + - name: Update the change log with the approximate release date + run: | + date=$(date "+%Y-%m-%d") + sed -Ei "s/^## Unreleased$/## Version ${STABLE_VERSION}\/${UNSTABLE_VERSION} ($date)/" CHANGELOG.md + + - name: Use CLA approved github bot + run: .github/scripts/use-cla-approved-github-bot.sh + + - name: Create pull request against the release branch + env: + # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows + GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} + run: | + message="Prepare release ${STABLE_VERSION}/${UNSTABLE_VERSION}" + branch="opentelemetrybot/prepare-release-${STABLE_VERSION}-${UNSTABLE_VERSION}" + + git commit -a -m "$message" + git push origin HEAD:$branch + gh pr create --title "[$RELEASE_BRANCH_NAME] $message" \ + --body "$message." \ + --head $branch \ + --base $RELEASE_BRANCH_NAME + + create-pull-request-against-main: + runs-on: ubuntu-latest + needs: prereqs + steps: + - uses: actions/checkout@v3 + + - name: Set environment variables + env: + PRERELEASE_VERSION: ${{ github.event.inputs.prerelease_version }} + run: | + if [[ -z $PRERELEASE_VERSION ]]; then + stable_version=$(./scripts/eachdist.py version --mode stable) + stable_version=${stable_version//.dev/} + else + stable_version=$PRERELEASE_VERSION + fi + + unstable_version=$(./scripts/eachdist.py version --mode prerelease) + unstable_version=${unstable_version//.dev/} + + if [[ $stable_version =~ ^([0-9]+)\.([0-9]+)\.0$ ]]; then + stable_major="${BASH_REMATCH[1]}" + stable_minor="${BASH_REMATCH[2]}" + stable_next_version="$stable_major.$((stable_minor + 1)).0" + elif [[ $stable_version =~ ^([0-9]+)\.([0-9]+)\.0 ]]; then + # pre-release version, e.g. 1.9.0rc2 + stable_major="${BASH_REMATCH[1]}" + stable_minor="${BASH_REMATCH[2]}" + stable_next_version="$stable_major.$stable_minor.0" + else + echo "unexpected stable_version: $stable_version" + exit 1 + fi + + if [[ $unstable_version =~ ^0\.([0-9]+)b[0-9]+$ ]]; then + unstable_minor="${BASH_REMATCH[1]}" + else + echo "unexpected unstable_version: $unstable_version" + exit 1 + fi + + unstable_next_version="0.$((unstable_minor + 1))b0" + + echo "STABLE_VERSION=${stable_version}" >> $GITHUB_ENV + echo "STABLE_NEXT_VERSION=${stable_next_version}.dev" >> $GITHUB_ENV + + echo "UNSTABLE_VERSION=${unstable_version}" >> $GITHUB_ENV + echo "UNSTABLE_NEXT_VERSION=${unstable_next_version}.dev" >> $GITHUB_ENV + + - name: Update version + run: .github/scripts/update-version.sh $STABLE_NEXT_VERSION $UNSTABLE_NEXT_VERSION + + - name: Set up Python 3.9 + uses: actions/setup-python@v2 + with: + python-version: 3.9 + - name: Install tox + run: pip install tox==3.27.1 + - name: run tox + run: tox -e generate + + - name: Update the change log on main + run: | + # the actual release date on main will be updated at the end of the release workflow + date=$(date "+%Y-%m-%d") + sed -Ei "s/^## Unreleased$/## Unreleased\n\n## Version ${STABLE_VERSION}\/${UNSTABLE_VERSION} ($date)/" CHANGELOG.md + + - name: Use CLA approved github bot + run: .github/scripts/use-cla-approved-github-bot.sh + + - name: Create pull request against main + env: + # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows + GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} + run: | + message="Update version to ${STABLE_NEXT_VERSION}/${UNSTABLE_NEXT_VERSION}" + body="Update version to \`${STABLE_NEXT_VERSION}/${UNSTABLE_NEXT_VERSION}\`." + branch="opentelemetrybot/update-version-to-${STABLE_NEXT_VERSION}-${UNSTABLE_NEXT_VERSION}" + + git commit -a -m "$message" + git push origin HEAD:$branch + gh pr create --title "$message" \ + --body "$body" \ + --head $branch \ + --base main \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 0921357cb..000000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Publish - -on: - release: - types: [published] - -jobs: - publish: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - uses: actions/setup-python@v1 - with: - python-version: '3.7' - - name: Build wheels - run: ./scripts/build.sh - - name: Install twine - run: | - pip install twine - # The step below publishes to testpypi in order to catch any issues - # with the package configuration that would cause a failure to upload - # to pypi. One example of such a failure is if a classifier is - # rejected by pypi (e.g "3 - Beta"). This would cause a failure during the - # middle of the package upload causing the action to fail, and certain packages - # might have already been updated, this would be bad. - - name: Publish to TestPyPI - env: - TWINE_USERNAME: '__token__' - TWINE_PASSWORD: ${{ secrets.test_pypi_token }} - run: | - twine upload --repository testpypi --skip-existing --verbose dist/* - - name: Publish to PyPI - env: - TWINE_USERNAME: '__token__' - TWINE_PASSWORD: ${{ secrets.pypi_password }} - run: | - twine upload --skip-existing --verbose dist/* diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..818ccdc68 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,205 @@ +name: Release +on: + workflow_dispatch: + +jobs: + release: + runs-on: ubuntu-latest + steps: + - run: | + if [[ $GITHUB_REF_NAME != release/* ]]; then + echo this workflow should only be run against release branches + exit 1 + fi + + - uses: actions/checkout@v3 + + - name: Set environment variables + run: | + stable_version=$(./scripts/eachdist.py version --mode stable) + unstable_version=$(./scripts/eachdist.py version --mode prerelease) + + if [[ $stable_version =~ ^([0-9]+)\.([0-9]+)\.([0-9]+) ]]; then + stable_major="${BASH_REMATCH[1]}" + stable_minor="${BASH_REMATCH[2]}" + stable_patch="${BASH_REMATCH[3]}" + else + echo "unexpected stable_version: $stable_version" + exit 1 + fi + if [[ $stable_patch != 0 ]]; then + if [[ $unstable_version =~ ^0\.([0-9]+)b([0-9]+)$ ]]; then + unstable_minor="${BASH_REMATCH[1]}" + unstable_patch="${BASH_REMATCH[2]}" + else + echo "unexpected unstable_version: $unstable_version" + exit 1 + fi + if [[ $unstable_patch != 0 ]]; then + prior_version_when_patch="$stable_major.$stable_minor.$((stable_patch - 1))/0.${unstable_minor}b$((unstable_patch - 1))" + fi + fi + + echo "STABLE_VERSION=$stable_version" >> $GITHUB_ENV + echo "UNSTABLE_VERSION=$unstable_version" >> $GITHUB_ENV + + echo "PRIOR_VERSION_WHEN_PATCH=$prior_version_when_patch" >> $GITHUB_ENV + + # check out main branch to verify there won't be problems with merging the change log + # at the end of this workflow + - uses: actions/checkout@v3 + with: + ref: main + + - run: | + if [[ -z $PRIOR_VERSION_WHEN_PATCH ]]; then + # not making a patch release + if ! grep --quiet "^## Version ${STABLE_VERSION}/${UNSTABLE_VERSION} " CHANGELOG.md; then + echo the pull request generated by prepare-release-branch.yml needs to be merged first + exit 1 + fi + fi + + # back to the release branch + - uses: actions/checkout@v3 + + # next few steps publish to pypi + - uses: actions/setup-python@v1 + with: + python-version: '3.7' + + - name: Build wheels + run: ./scripts/build.sh + + - name: Install twine + run: | + pip install twine + + # The step below publishes to testpypi in order to catch any issues + # with the package configuration that would cause a failure to upload + # to pypi. One example of such a failure is if a classifier is + # rejected by pypi (e.g "3 - Beta"). This would cause a failure during the + # middle of the package upload causing the action to fail, and certain packages + # might have already been updated, this would be bad. + - name: Publish to TestPyPI + env: + TWINE_USERNAME: '__token__' + TWINE_PASSWORD: ${{ secrets.test_pypi_token }} + run: | + twine upload --repository testpypi --skip-existing --verbose dist/* + + - name: Publish to PyPI + env: + TWINE_USERNAME: '__token__' + TWINE_PASSWORD: ${{ secrets.pypi_password }} + run: | + twine upload --skip-existing --verbose dist/* + + - name: Generate release notes + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # conditional block not indented because of the heredoc + if [[ ! -z $PRIOR_VERSION_WHEN_PATCH ]]; then + cat > /tmp/release-notes.txt << EOF + This is a patch release on the previous $PRIOR_VERSION_WHEN_PATCH release, fixing the issue(s) below. + + EOF + fi + + # CHANGELOG_SECTION.md is also used at the end of the release workflow + # for copying the change log updates to main + sed -n "0,/^## Version ${STABLE_VERSION}\/${UNSTABLE_VERSION} /d;/^## Version /q;p" CHANGELOG.md \ + > /tmp/CHANGELOG_SECTION.md + + # the complex perl regex is needed because markdown docs render newlines as soft wraps + # while release notes render them as line breaks + perl -0pe 's/(?> /tmp/release-notes.txt + + - name: Create GitHub release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create --target $GITHUB_REF_NAME \ + --title "Version ${STABLE_VERSION}/${UNSTABLE_VERSION}" \ + --notes-file /tmp/release-notes.txt \ + --discussion-category announcements \ + v$STABLE_VERSION + + - uses: actions/checkout@v3 + with: + # the step below is creating a pull request against main + ref: main + + - name: Copy change log updates to main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + if [[ -z $PRIOR_VERSION_WHEN_PATCH ]]; then + # this was not a patch release, so the version exists already in the CHANGELOG.md + + # update the release date + date=$(gh release view v$STABLE_VERSION --json publishedAt --jq .publishedAt | sed 's/T.*//') + sed -Ei "s/## Version ${STABLE_VERSION}\/${UNSTABLE_VERSION} .*/## Version ${STABLE_VERSION}\/${UNSTABLE_VERSION} ($date)/" CHANGELOG.md + + # the entries are copied over from the release branch to support workflows + # where change log entries may be updated after preparing the release branch + + # copy the portion above the release, up to and including the heading + sed -n "0,/^## Version ${STABLE_VERSION}\/${UNSTABLE_VERSION} ($date)/p" CHANGELOG.md > /tmp/CHANGELOG.md + + # copy the release notes + cat /tmp/CHANGELOG_SECTION.md >> /tmp/CHANGELOG.md + + # copy the portion below the release + sed -n "0,/^## Version ${STABLE_VERSION}\/${UNSTABLE_VERSION} /d;0,/^## Version /{/^## Version/!d};p" CHANGELOG.md \ + >> /tmp/CHANGELOG.md + + # update the real CHANGELOG.md + cp /tmp/CHANGELOG.md CHANGELOG.md + else + # this was a patch release, so the version does not exist already in the CHANGELOG.md + + # copy the portion above the top-most release, not including the heading + sed -n "0,/^## Version /{ /^## Version /!p }" CHANGELOG.md > /tmp/CHANGELOG.md + + # add the heading + date=$(gh release view v$STABLE_VERSION --json publishedAt --jq .publishedAt | sed 's/T.*//') + echo "## Version ${STABLE_VERSION}/${UNSTABLE_VERSION} ($date)" >> /tmp/CHANGELOG.md + + # copy the release notes + cat /tmp/CHANGELOG_SECTION.md >> /tmp/CHANGELOG.md + + # copy the portion starting from the top-most release + sed -n "/^## Version /,\$p" CHANGELOG.md >> /tmp/CHANGELOG.md + + # update the real CHANGELOG.md + cp /tmp/CHANGELOG.md CHANGELOG.md + fi + + - name: Use CLA approved github bot + run: .github/scripts/use-cla-approved-github-bot.sh + + - name: Create pull request against main + env: + # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows + GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} + run: | + message="Copy change log updates from $GITHUB_REF_NAME" + body="Copy log updates from \`$GITHUB_REF_NAME\`." + branch="opentelemetrybot/copy-change-log-updates-from-${GITHUB_REF_NAME//\//-}" + + if [[ -z $PRIOR_VERSION_WHEN_PATCH ]]; then + if git diff --quiet; then + echo there are no updates needed to the change log on main, not creating pull request + exit 0 # success + fi + fi + + git commit -a -m "$message" + git push origin HEAD:$branch + gh pr create --title "$message" \ + --body "$body" \ + --head $branch \ + --base main \ No newline at end of file diff --git a/.github/workflows/update-sha.yml b/.github/workflows/update-sha.yml new file mode 100644 index 000000000..e5418d929 --- /dev/null +++ b/.github/workflows/update-sha.yml @@ -0,0 +1,50 @@ +name: Update SHA + +on: issue_comment + +jobs: + update-pr-sha: + name: Update SHA + if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, 'update-sha') }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + token: ${{ secrets.BOT_TOKEN }} + + # would have been lit if github supported string split expression + - name: Extract branch name from comment to get commit SHA + uses: jungwinter/split@v2 + id: split + with: + msg: ${{ github.event.comment.body }} + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.9' + + - name: Use CLA approved github bot + run: .github/scripts/use-cla-approved-github-bot.sh + + - name: Checkout Pull Request + env: + GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} + run: | + PR_URL="${{ github.event.issue.pull_request.url }}" + PR_NUM=${PR_URL##*/} + echo "Checking out from PR #$PR_NUM based on URL: $PR_URL" + hub pr checkout $PR_NUM + + # caching is not supported for this event type + - name: Run script + run: | + python -m pip install requests==2.28.1 ruamel.yaml==0.17.21 + python scripts/update_sha.py --branch ${{ steps.split.outputs._1 }} + + - name: Commit and Push changes + env: + GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} + run: | + git commit -a -m "Update SHA" + git push diff --git a/RELEASING.md b/RELEASING.md index bf7692229..01945165e 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,93 +1,90 @@ -# Releasing OpenTelemetry Packages (for maintainers only) -This document explains how to publish all OT modules at version x.y.z. Ensure that you’re following semver when choosing a version number. +# Release instructions -Release Process: -* [Checkout a clean repo](#checkout-a-clean-repo) -* [Update versions](#update-versions) -* [Create a new branch](#create-a-new-branch) -* [Open a Pull Request](#open-a-pull-request) -* [Create a Release](#Create-a-Release) -* [Move stable tag](#Move-stable-tag) -* [Update main](#Update-main) -* [Check PyPI](#Check-PyPI) -* [Troubleshooting](#troubleshooting) +## Preparing a new major or minor release -## Checkout a clean repo -To avoid pushing untracked changes, check out the repo in a new dir +* Run the [Prepare release branch workflow](https://github.com/open-telemetry/opentelemetry-python/actions/workflows/prepare-release-branch.yml). + * Press the "Run workflow" button, and leave the default branch `main` selected. + * If making a pre-release of stable components (e.g. release candidate), + enter the pre-release version number, e.g. `1.9.0rc2`. + (otherwise the workflow will pick up the version from `main` and just remove the `.dev` suffix). + * Review and merge the two pull requests that it creates + (one is targeted to the release branch and one is targeted to `main`). -## Update versions -The update of the version information relies on the information in eachdist.ini to identify which packages are stable, prerelease or -experimental. Update the desired version there to begin the release process. +## Preparing a new patch release -## Create a new branch -The following script does the following: -- update main locally -- creates a new release branch `release/` -- updates version and changelog files -- commits the change +* Backport pull request(s) to the release branch. + * Run the [Backport workflow](https://github.com/open-telemetry/opentelemetry-python/actions/workflows/backport.yml). + * Press the "Run workflow" button, then select the release branch from the dropdown list, + e.g. `release/v1.9.x`, then enter the pull request number that you want to backport, + then click the "Run workflow" button below that. + * Review and merge the backport pull request that it generates. +* Merge a pull request to the release branch updating the `CHANGELOG.md`. + * The heading for the unreleased entries should be `## Unreleased`. +* Run the [Prepare patch release workflow](https://github.com/open-telemetry/opentelemetry-python/actions/workflows/prepare-patch-release.yml). + * Press the "Run workflow" button, then select the release branch from the dropdown list, + e.g. `release/v1.9.x`, and click the "Run workflow" button below that. + * Review and merge the pull request that it creates for updating the version. -*NOTE: This script was run by a GitHub Action but required the Action bot to be excluded from the CLA check, which it currently is not.* +## Making the release -```bash -./scripts/prepare_release.sh -``` +* Run the [Release workflow](https://github.com/open-telemetry/opentelemetry-python/actions/workflows/release.yml). + * Press the "Run workflow" button, then select the release branch from the dropdown list, + e.g. `release/v1.9.x`, and click the "Run workflow" button below that. + * This workflow will publish the artifacts and publish a GitHub release with release notes based on the change log. + * Review and merge the pull request that it creates for updating the change log in main + (note that if this is not a patch release then the change log on main may already be up-to-date, + in which case no pull request will be created). -## Open a Pull Request +## Notes about version numbering for stable components -The PR should be opened from the `release/` branch created as part of running `prepare_release.sh` in the steps above. +* The version number for stable components in the `main` branch is always `X.Y.0.dev`, + where `X.Y.0` represents the next minor release. +* When the release branch is created, you can opt to make a "pre-release", e.g. `X.Y.0rc2`. +* If you ARE NOT making a "pre-release": + * A "long-term" release branch will be created, e.g. `release/v1.9.x-0.21bx` (notice the wildcard x's). + Later on, after the initial release, you can backport PRs to a "long-term" release branch and make patch releases + from it. + * The version number for stable components in the release branch will be bumped to remove the `.dev`, + e.g. `X.Y.0`. + * The version number for stable components in the `main` branch will be bumped to the next version, + e.g. `X.{Y+1}.0.dev`. +* If you ARE making a "pre-release": + * A "short-term" release branch will be created, e.g. `release/v1.9.0rc2-0.21b0` (notice the precise version with no + wildcard x's). "Short-term" release branches do not support backports or patch releases after the initial release. + * The version number for stable components in the `main` branch will not be bumped, e.g. it will remain `X.Y.0.dev` + since the next minor release will still be `X.Y.0`. -## Create a Release +## Notes about version numbering for unstable components -- Create the GH release from the main branch, using a new tag for this micro version, e.g. `v0.7.0` -- Copy the changelogs from all packages that changed into the release notes (and reformat to remove hard line wraps) +* The version number for unstable components in the `main` branch is always `0.Yb0.dev`, + where `0.Yb0` represents the next minor release. + * _Question: Is "b" (beta) redundant on "0." releases, or is this a python thing? I'm wondering if we can change it to `0.Y.0` to match up with the practice in js and go repos._ +* Unstable components do not need "pre-releases", and so whether or not you are making a "pre-release" of stable + components: + * The version number for unstable components in the release branch will be bumped to remove the `.dev`, + e.g. `0.Yb0`. + * The version number for unstable components in the `main` branch will be bumped to the next version, + e.g. `0.{Y+1}b0.dev`. +## After the release -## Check PyPI - -This should be handled automatically on release by the [publish action](https://github.com/open-telemetry/opentelemetry-python/blob/main/.github/workflows/publish.yml). - -- Check the [action logs](https://github.com/open-telemetry/opentelemetry-python/actions?query=workflow%3APublish) to make sure packages have been uploaded to PyPI -- Check the release history (e.g. https://pypi.org/project/opentelemetry-api/#history) on PyPI - -If for some reason the action failed, see [Publish failed](#publish-failed) below - -## Move stable tag - -This will ensure the docs are pointing at the stable release. - -```bash -git tag -d stable -git tag stable -git push --delete origin tagname -git push origin stable -``` - -To validate this worked, ensure the stable build has run successfully: https://readthedocs.org/projects/opentelemetry-python/builds/. If the build has not run automatically, it can be manually trigger via the readthedocs interface. - -## Update main - -Ensure the version and changelog updates have been applied to main. Update the versions in eachdist.ini once again this time to include the `.dev0` tag and -run eachdist once again: -```bash -./scripts/eachdist.py update_versions --versions stable,prerelease -``` - -If the diff includes significant changes, create a pull request to commit the changes and once the changes are merged, click the "Run workflow" button for the Update [OpenTelemetry Website Docs](https://github.com/open-telemetry/opentelemetry-python/actions/workflows/docs-update.yml) GitHub Action. - -## Hotfix procedure - -A `hotfix` is defined as a small change developed to correct a bug that should be released as quickly as possible. Due to the nature of hotfixes, they usually will only affect one or a few packages. Therefore, it usually is not necessary to go through the entire release process outlined above for hotfixes. Follow the below steps how to release a hotfix: - -1. Identify the packages that are affected by the bug. Make the changes to those packages, merging to `main`, as quickly as possible. -2. On your local machine, remove the `dev0` tags from the version number and increment the patch version number. -3. On your local machine, update `CHANGELOG.md` with the date of the hotfix change. -4. With administrator privileges for PyPi, manually publish the affected packages. - a. Install [twine](https://pypi.org/project/twine/) - b. Navigate to where the `setup.py` file exists for the package you want to publish. - c. Run `python setup.py sdist bdist_wheel`. You may have to install [wheel](https://pypi.org/project/wheel/) as well. - d. Validate your built distributions by running `twine check dist/*`. - e. Upload distributions to PyPi by running `twine upload dist/*`. -5. Note that since hotfixes are manually published, the build scripts for publish after creating a release are not run. +* Check PyPI + * This should be handled automatically on release by the [publish action](https://github.com/open-telemetry/opentelemetry-python/blob/main/.github/workflows/publish.yml). + * Check the [action logs](https://github.com/open-telemetry/opentelemetry-python/actions?query=workflow%3APublish) to make sure packages have been uploaded to PyPI + * Check the release history (e.g. https://pypi.org/project/opentelemetry-api/#history) on PyPI + * If for some reason the action failed, see [Publish failed](#publish-failed) below +* Move stable tag + * Run the following (TODO automate): + ```bash + git tag -d stable + git tag stable + git push --delete origin tagname + git push origin stable + ``` + * This will ensure the docs are pointing at the stable release. + * To validate this worked, ensure the stable build has run successfully: + https://readthedocs.org/projects/opentelemetry-python/builds/. + If the build has not run automatically, it can be manually trigger via the readthedocs interface. ## Troubleshooting diff --git a/dev-requirements.txt b/dev-requirements.txt index 7938bda18..a8efb950d 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -16,3 +16,5 @@ mypy-protobuf>=1.23 protobuf~=3.13 markupsafe==2.0.1 codespell==2.1.0 +requests==2.28.1 +ruamel.yaml==0.17.21 diff --git a/scripts/generate_instrumentation_metapackage.py b/scripts/generate_instrumentation_metapackage.py index ddc13a047..ad5d0b5e3 100755 --- a/scripts/generate_instrumentation_metapackage.py +++ b/scripts/generate_instrumentation_metapackage.py @@ -71,7 +71,9 @@ def main(): root_path, "opentelemetry-contrib-instrumentations", "pyproject.toml" ) - deps = [f"{pkg}=={version}" for pkg, version in dependencies] + deps = [ + f"{pkg.strip()}=={version.strip()}" for pkg, version in dependencies + ] with open(pyproject_toml_path, "rb") as file: pyproject_toml = tomli.load(file) diff --git a/scripts/update_sha.py b/scripts/update_sha.py new file mode 100644 index 000000000..d74ccc12d --- /dev/null +++ b/scripts/update_sha.py @@ -0,0 +1,60 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# pylint: disable=import-error,unspecified-encoding + +import argparse + +import requests +from ruamel.yaml import YAML + +API_URL = ( + "https://api.github.com/repos/open-telemetry/opentelemetry-python/commits/" +) +WORKFLOW_FILE = ".github/workflows/test.yml" + + +def get_sha(branch): + url = API_URL + branch + response = requests.get(url) + response.raise_for_status() + return response.json()["sha"] + + +def update_sha(sha): + yaml = YAML() + yaml.preserve_quotes = True + with open(WORKFLOW_FILE, "r") as file: + workflow = yaml.load(file) + workflow["env"]["CORE_REPO_SHA"] = sha + with open(WORKFLOW_FILE, "w") as file: + yaml.dump(workflow, file) + + +def main(): + args = parse_args() + sha = get_sha(args.branch) + update_sha(sha) + + +def parse_args(): + parser = argparse.ArgumentParser( + description="Updates the SHA in the workflow file" + ) + parser.add_argument("-b", "--branch", help="branch to use") + return parser.parse_args() + + +if __name__ == "__main__": + main()