1# The purpose of this workflow is to orchestrate Wasmtime's release process as
2# much as possible. This specific workflow is responsible for a few timed parts
3# of the process:
4#
5# * On the 5th of every month a new release branch is automatically created and
6#   the version number of the `main` branch is increased
7# * On the 20th of every month the previous release branch is published.
8#
9# This automation is all done through PRs except for the creation of the release
10# branch itself which is an write-action performed by this script. Otherwise
11# humans are ideally reviewing and rubber-stamping the output of the script all
12# other steps of the way.
13#
14# Note that this script also helps manage patch releases by sending a PR to the
15# release branch with a bumped version number for all crates with a patch-bump.
16
17name: "Automated Release Process"
18on:
19  schedule:
20    # “At 00:00 on day-of-month 5.”
21    #
22    # https://crontab.guru/#0_0_5_*_*
23    - cron: '0 0 5 * *'
24    - cron: '0 0 20 * *'
25
26  # Allow manually triggering this request via the button at
27  # https://github.com/bytecodealliance/wasmtime/actions/workflows/release-process.yml
28  workflow_dispatch:
29    inputs:
30      action:
31        description: 'Publish script argument: "cut", "release-latest", or "release-patch"'
32        required: false
33        default: 'cut'
34
35jobs:
36  release_process:
37    if: github.repository == 'bytecodealliance/wasmtime'
38    name: Run the release process
39    runs-on: ubuntu-latest
40    steps:
41      - uses: actions/checkout@v2
42        with:
43          submodules: true
44      - name: Setup
45        run: |
46          rustc scripts/publish.rs
47          git config user.name 'Wasmtime Publish'
48          git config user.email '[email protected]'
49          git remote set-url origin https://git:${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/${{ github.repository }}
50
51      - name: Bump major version number
52        run: |
53          set -ex
54          # Push the current contents of `main` to a new release branch
55          cur=$(./ci/print-current-version.sh)
56          git push origin HEAD:release-$cur
57
58          # Update version numbers and make a commit indicating that. Note that
59          # on merge this will not trigger a publish.
60          ./publish bump
61          num=$(./ci/print-current-version.sh)
62
63          # Add a new section to the release notes for the new version.
64          cp RELEASES.md backup-releases
65          sed "s/VERSION/$num/" ci/RELEASES-template.md > RELEASES.md
66          cat backup-releases >> RELEASES.md
67          rm backup-releases
68
69          # Commit all of the above changes.
70          git commit -am "Bump Wasmtime to $num"
71
72          # Push the result to a branch and setup metadata for the step below
73          # that creates a PR
74          git push origin HEAD:ci/bump-to-$num
75          echo "PR_HEAD=ci/bump-to-$num" >> $GITHUB_ENV
76          echo "PR_TITLE=Bump Wasmtime to $num" >> $GITHUB_ENV
77          echo "PR_BASE=main" >> $GITHUB_ENV
78          cat > pr-body <<-EOF
79          This is an [automated pull request][process] from CI which indicates
80          that the next [\`release-$cur\` branch][branch] has been created and
81          the \`main\` branch is getting its version number bumped from $cur to
82          $num.
83
84          Maintainers should take a moment to review the [release
85          notes][RELEASES.md] for $cur, and if any changes are necessary send
86          PRs to the \`main\` branch to update [RELEASES.md] and then backport
87          these PRs to the [release branch][branch].
88
89          Maintainers should also review that aarch64-apple-darwin builds
90          are passing via [embark's CI](https://buildkite.com/embark-studios/wasmtime-aarch64-apple-darwin).
91
92          Another automated PR will be made in roughly 2 weeks time when for
93          the actual release itself.
94
95          If any issues arise on the \`main\` branch before the release is made
96          then the issue should first be fixed on \`main\` and then backported
97          to the \`release-$cur\` branch.
98
99          [RELEASES.md]: https://github.com/${{ github.repository }}/blob/main/RELEASES.md
100          [branch]: https://github.com/${{ github.repository }}/tree/release-$cur
101          [process]: https://docs.wasmtime.dev/contributing-release-process.html
102          EOF
103        if: >-
104          github.event.schedule == '0 0 5 * *' ||
105          github.event.inputs.action == 'cut'
106
107      - name: Perform latest release
108        run: |
109          set -ex
110          git fetch origin
111
112          # Determine the latest release branch
113          rustc ci/find-latest-release.rs -o /tmp/find-latest-release
114          cur=`/tmp/find-latest-release`
115
116          # Update the release date of $cur in RELEASES.md
117          rustc ci/update-release-date.rs -o /tmp/update-release-date
118          /tmp/update-release-date $(date +'%Y-%m-%d')
119
120          git commit -a -F-<<EOF
121          Update release date of Wasmtime $cur
122
123          [skip ci]
124          EOF
125          git push origin HEAD:ci/release-date-for-$cur
126
127          # In addition to the PR we'll make below to perform the actual release
128          # make a second PR to the `main` branch to note the release date in
129          # the release notes.
130          cat > pr-body <<-EOF
131          This is an [automated pull request][process] from CI which is updating
132          the release date of Wasmtime $cur to today. This PR's base branch
133          is \`main\` and a second PR will be coming to perform the actual
134          release which will be targeted at \`release-$cur\`.
135
136          [process]: https://docs.wasmtime.dev/contributing-release-process.html
137          EOF
138          body=$(jq -sR < ./pr-body)
139          curl --include --request POST \
140            https://api.github.com/repos/${{ github.repository }}/pulls \
141            --header "Authorization: token ${{ secrets.PERSONAL_ACCESS_TOKEN }}" \
142            --data @- << EOF
143          {
144            "head": "ci/release-date-for-$cur",
145            "base": "main",
146            "title": "Update release date of Wasmtime $cur",
147            "body": $body,
148            "maintainer_can_modify": true
149          }
150          EOF
151
152          # Move to the most recent release branch, update the release date and
153          # commit it, indicating that the commit is what will get tagged and
154          # released
155          git reset --hard origin/release-$cur
156          sed -i "s/^Unreleased/Released $(date +'%Y-%m-%d')/" RELEASES.md
157          git commit -a -F-<<EOF
158          Release Wasmtime $cur
159
160          [automatically-tag-and-release-this-commit]
161          EOF
162
163          # Push the result to a branch and setup metadata for the step below
164          # that creates a PR
165          git push origin HEAD:ci/release-$cur
166          echo "PR_HEAD=ci/release-$cur" >> $GITHUB_ENV
167          echo "PR_TITLE=Release Wasmtime $cur" >> $GITHUB_ENV
168          echo "PR_BASE=release-$cur" >> $GITHUB_ENV
169          cat > pr-body <<-EOF
170          This is an [automated pull request][process] from CI which is
171          intended to notify maintainers that it's time to release Wasmtime
172          $cur. The [release branch][branch] was created roughly two weeks ago
173          and it's now time for it to be published and released.
174
175          It's recommended that maintainers double-check that [RELEASES.md]
176          is up-to-date and that there are no known issues before merging this
177          PR. When this PR is merged a release tag will automatically be
178          created, crates will be published, and CI artifacts will be produced.
179
180          [RELEASES.md]: https://github.com/${{ github.repository }}/blob/main/RELEASES.md
181          [process]: https://docs.wasmtime.dev/contributing-release-process.html
182          [branch]: https://github.com/${{ github.repository }}/tree/release-$cur
183          EOF
184        if: >-
185          github.event.schedule == '0 0 20 * *' ||
186          github.event.inputs.action == 'release-latest'
187
188      - name: Bump and release patch version number
189        run: |
190          set -ex
191          # Update version numbers on a patch basis and update RELEASES.md if a
192          # patch release marker is already in there. Note that this commit
193          # message indicates that on-merge a release will be made.
194          ./publish bump-patch
195          sed -i "s/^Unreleased/Released $(date +'%Y-%m-%d')/" RELEASES.md
196          num=$(./ci/print-current-version.sh)
197          git commit -a -F-<<EOF
198          Release Wasmtime $num
199
200          [automatically-tag-and-release-this-commit]
201          EOF
202
203          # Push the result to a branch and setup metadata for the step below
204          # that creates a PR
205          git push origin HEAD:ci/bump-to-$num
206          echo "PR_HEAD=ci/bump-to-$num" >> $GITHUB_ENV
207          echo "PR_TITLE=Release Wasmtime $num" >> $GITHUB_ENV
208          echo "PR_BASE=${{ github.ref_name }}" >> $GITHUB_ENV
209          cat > pr-body <<-EOF
210          This is an [automated pull request][process] from CI to create a patch
211          release for Wasmtime $num, requested by @${{ github.actor }}.
212
213          It's recommended that maintainers double-check that [RELEASES.md]
214          is up-to-date and that there are no known issues before merging this
215          PR. When this PR is merged a release tag will automatically be
216          created, crates will be published, and CI artifacts will be produced.
217
218          [RELEASES.md]: https://github.com/${{ github.repository }}/blob/main/RELEASES.md
219          [process]: https://docs.wasmtime.dev/contributing-release-process.html
220          EOF
221
222        if: github.event.inputs.action == 'release-patch'
223
224      - name: Make a PR
225        # Note that the syntax here is kinda funky, and the general gist is that
226        # I couldn't figure out a good way to have a multiline string-literal
227        # become a json-encoded string literal to send to GitHub. This
228        # represents my best attempt.
229        run: |
230          set -ex
231          body=$(jq -sR < ./pr-body)
232
233          curl --include --request POST \
234            https://api.github.com/repos/${{ github.repository }}/pulls \
235            --header "Authorization: token ${{ secrets.PERSONAL_ACCESS_TOKEN }}" \
236            --data @- << EOF
237          {
238            "head": "$PR_HEAD",
239            "base": "$PR_BASE",
240            "title": "$PR_TITLE",
241            "body": $body,
242            "maintainer_can_modify": true
243
244          }
245          EOF
246