diff --git a/.github/actions/publish-release/action.yml b/.github/actions/publish-release/action.yml new file mode 100644 index 0000000000..796381fd67 --- /dev/null +++ b/.github/actions/publish-release/action.yml @@ -0,0 +1,84 @@ +name: 'Maybe perform a release' +description: 'Steps to perform a conditional release of this repository' + +inputs: + cargo_token: + description: 'token used to publish crates' + required: false + +runs: + using: composite + steps: + # If this commit log has an indicator saying that a tag should be made. If + # so create one and push it. + - name: Test if tag is needed + run: | + git log ${{ github.event.before }}...${{ github.event.after }} | tee main.log + version=$(./ci/print-current-version.sh) + echo "version: $version" + echo "version=$version" >> $GITHUB_OUTPUT + echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + if grep -q "automatically-tag-and-release-this-commit" main.log; then + echo push-tag + echo "push_tag=yes" >> $GITHUB_OUTPUT + else + echo no-push-tag + echo "push_tag=no" >> $GITHUB_OUTPUT + fi + shell: bash + id: tag + + - name: Push the tag + run: | + git_refs_url=$(jq .repository.git_refs_url $GITHUB_EVENT_PATH | tr -d '"' | sed 's/{\/sha}//g') + curl -iX POST $git_refs_url \ + -H "Authorization: token ${{ github.token }}" \ + -d @- << EOF + { + "ref": "refs/tags/v${{ steps.tag.outputs.version }}", + "sha": "${{ steps.tag.outputs.sha }}" + } + EOF + shell: bash + if: steps.tag.outputs.push_tag == 'yes' + + # Download all github actions artifact for this commit. We're either running + # on `main` after the merge queue or on a release branch after the rest of + # CI, so use the github API to find the artifacts for consistency. + - run: | + sha=${{ github.sha }} + run_id=$( + gh api -H 'Accept: application/vnd.github+json' \ + /repos/${{ github.repository }}/actions/workflows/main.yml/runs\?exclude_pull_requests=true \ + | jq '.workflow_runs' \ + | jq "map(select(.head_commit.id == \"$sha\"))[0].id" \ + ) + gh run download $run_id + ls + find bins-* + mkdir dist + mv bins-*/* dist + shell: bash + env: + GH_TOKEN: ${{ github.token }} + + # Conditionally make a release if a tag was made. + - uses: softprops/action-gh-release@v1 + if: steps.tag.outputs.push_tag == 'yes' + with: + files: "dist/*" + generate_release_notes: true + tag_name: v${{ steps.tag.outputs.version }} + + # Conditionally run crate publishes if the token is present. + - run: rustup update stable && rustup default stable + shell: bash + + - run: | + rm -rf dist main.log + rustc ci/publish.rs + ./publish publish + shell: bash + env: + CARGO_REGISTRY_TOKEN: ${{ inputs.cargo_token }} + if: steps.tag.outputs.push_tag == 'yes' && github.repository_owner == 'bytecodealliance' diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 72462c24bc..c4b1790148 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,7 +1,14 @@ name: CI on: + # Run CI for PRs to `main` and to release branches. pull_request: + # This is the CI that runs for PRs-to-merge. merge_group: + # Run full CI on pushes to release branches since the merge queue can't be + # used with for all release branches (wildcard pattern turns that off) + push: + branches: + - 'release-*' # Cancel any in-flight jobs for the same PR/branch so there's only one active # at a time @@ -329,3 +336,22 @@ jobs: - name: Report failure on cancellation if: ${{ contains(needs.*.result, 'cancelled') || cancelled() }} run: exit 1 + + # Once CI has finished on `release-*` branches test to see if a release needs + # to be made based on the commits of this push. + maybe-trigger-tag: + runs-on: ubuntu-latest + needs: ci-status + if: | + always() + && needs.ci-status.result == 'success' + && github.event_name == 'push' + && startsWith(github.ref, 'refs/heads/release-') + steps: + - uses: actions/checkout@v4 + with: + submodules: true + fetch-depth: 0 + - uses: ./.github/actions/publish-release + with: + cargo_token: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/.github/workflows/playground.yml b/.github/workflows/playground.yml index 190dfe99b4..9ce36d4db7 100644 --- a/.github/workflows/playground.yml +++ b/.github/workflows/playground.yml @@ -46,7 +46,7 @@ jobs: deploy: name: Deploy playground - if: github.ref == 'refs/heads/main' + if: github.ref == 'refs/heads/main' && github.repository_owner == 'bytecodealliance' needs: build permissions: pages: write diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e293d60039..4d53048ade 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,6 +1,7 @@ -# Publication half of the release process for this repository. This runs on -# pushes to `main` and will detect a magical string in commit messages. When -# found a tag will be created, pushed, and then everything is published. +# Publication of the `main` branch. +# +# Commits to `main` go through the merge queue first to produce artifacts and +# test results. If a special commit marker is found then a publish is made. name: Publish Artifacts on: @@ -14,76 +15,11 @@ jobs: create_tag: name: Publish artifacts of build runs-on: ubuntu-latest - if: | - github.repository_owner == 'bytecodealliance' - && github.event_name == 'push' - && github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v4 with: submodules: true fetch-depth: 0 - - - run: rustup update stable && rustup default stable - - # If this is a push to `main` see if the push has an indicator saying that - # a tag should be made. If so create one and push it. - - name: Test if tag is needed - run: | - git log ${{ github.event.before }}...${{ github.event.after }} | tee main.log - version=$(./ci/print-current-version.sh) - echo "version: $version" - echo "version=$version" >> $GITHUB_OUTPUT - echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT - if grep -q "automatically-tag-and-release-this-commit" main.log; then - echo push-tag - echo "push_tag=yes" >> $GITHUB_OUTPUT - else - echo no-push-tag - echo "push_tag=no" >> $GITHUB_OUTPUT - fi - id: tag - - - name: Push the tag - run: | - git_refs_url=$(jq .repository.git_refs_url $GITHUB_EVENT_PATH | tr -d '"' | sed 's/{\/sha}//g') - curl -iX POST $git_refs_url \ - -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ - -d @- << EOF - { - "ref": "refs/tags/v${{ steps.tag.outputs.version }}", - "sha": "${{ steps.tag.outputs.sha }}" - } - EOF - if: steps.tag.outputs.push_tag == 'yes' - - - run: | - sha=${{ github.sha }} - run_id=$( - gh api -H 'Accept: application/vnd.github+json' \ - /repos/${{ github.repository }}/actions/workflows/main.yml/runs\?exclude_pull_requests=true \ - | jq '.workflow_runs' \ - | jq "map(select(.head_commit.id == \"$sha\"))[0].id" \ - ) - gh run download $run_id - ls - find bins-* - mkdir dist - mv bins-*/* dist - env: - GH_TOKEN: ${{ github.token }} - - - uses: softprops/action-gh-release@v1 - if: steps.tag.outputs.push_tag == 'yes' + - uses: ./.github/actions/publish-release with: - files: "dist/*" - generate_release_notes: true - tag_name: v${{ steps.tag.outputs.version }} - - - run: | - rm -rf dist main.log - rustc ci/publish.rs - ./publish publish - env: - CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - if: steps.tag.outputs.push_tag == 'yes' + cargo_token: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/.github/workflows/release-process.yml b/.github/workflows/release-process.yml index a9f9f91477..f0c7869c1c 100644 --- a/.github/workflows/release-process.yml +++ b/.github/workflows/release-process.yml @@ -56,7 +56,7 @@ jobs: git push origin HEAD:ci/release-$cur echo "PR_HEAD=ci/release-$cur" >> $GITHUB_ENV echo "PR_TITLE=Release ${{ github.event.repository.name }} $cur" >> $GITHUB_ENV - echo "PR_BASE=main" >> $GITHUB_ENV + echo "PR_BASE=${{ github.ref_name }}" >> $GITHUB_ENV cat > pr-body <<-EOF This is an automated pull request from CI to release ${{ github.event.repository.name }} $cur when merged. The commit