diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c0914e6..0b3abe6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,11 +1,12 @@ name: CI on: - create: - tags: push: + tags: + - 'wasi-sdk-*' branches: - main + pull_request: workflow_dispatch: @@ -200,3 +201,9 @@ jobs: labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max + + - name: Publish a draft release + if: startsWith(github.ref, 'refs/tags') + run: gh release create --draft --prerelease --generate-notes ${{ github.ref_name }} ./dist/* + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/RELEASING.md b/RELEASING.md index 6bc3879..1091c80 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,8 +1,5 @@ # Release Process -> **Note**: These instructions are out-of-date given the latest refactoring of -> the build system and should get updated before the next release. - To publish a new version of `wasi-sdk` as a GitHub release: 1. Tag a commit with an annotated tag. Note that this must be an annotated tag, @@ -17,49 +14,12 @@ To publish a new version of `wasi-sdk` as a GitHub release: git push origin $TAG ``` -2. Find a successful workflow that CI has run for the tag. That successful - workflow run will have build artifacts that need to be attached to the - release. One could search around in the GitHub [actions], but the following - script will list completed workflows for a tag (get a token [here][tokens]): - - ```shell script - ci/get-workflows-for-tag.sh $TAG $GITHUB_TOKEN - ``` - - [actions]: https://github.com/WebAssembly/wasi-sdk/actions - [tokens]: https://github.com/settings/tokens - -3. Check that the workflow built the artifacts for the given tag and that the - workflow completed successfully: - - ```shell script - ci/is-workflow-valid.sh $TAG $WORKFLOW_RUN_ID $GITHUB_TOKEN - ``` - -4. Download and unzip the workflow artifacts. Note that artifacts with `+m` or - `.m` suffixes indicate that the Git tree was modified. Expect some duplicates - since some of the same artifacts are built on multiple CI runners (e.g., - Windows, MacOS, Linux). The following script does all of this automatically: - - ```shell script - ci/download-workflow-artifacts.sh $WORKFLOW_RUN_ID $GITHUB_TOKEN - ``` - -5. Draft a new release. This could be done [manually][releases] but the - following script simplifies the uploading of all the files and auto-generates - the release description: - - ```shell script - ci/draft-release.sh $TAG $ARTIFACTS_DIR $GITHUB_TOKEN - ``` - - [releases]: https://github.com/WebAssembly/wasi-sdk/releases - -6. Publish the release; the previous step only creates a draft. Follow the link - in the previous step or navigate to the GitHub [releases] to review the - description, commit, tag, and assets before clicking "Publish." +2. Wait for the CI build of the tag to finish. This will automatically publish + a draft pre-release to [GitHub Releases](https://github.com/WebAssembly/wasi-sdk/releases). + Release notes are auto-generated and should be reviewed for accuracy. Once + everything looks good manually publish the release through the GitHub UI. -7. Remember to tag the wasi-libc repository with the new `$TAG` version. +3. Remember to tag the wasi-libc repository with the new `$TAG` version. ```shell script git submodule status -- src/wasi-libc # grab $WASI_LIBC_COMMIT from the output diff --git a/ci/download-workflow-artifacts.sh b/ci/download-workflow-artifacts.sh deleted file mode 100755 index 543f93c..0000000 --- a/ci/download-workflow-artifacts.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env bash -set -e - -# This script downloads and unzips the artifacts produced in a workflow run. The -# script has several pre-requisites: -# - some standard Bash tools (curl, unzip) and one slightly more rare one (jq) -# - the ID of a workflow run that has run successfully--this is where we -# retrieve the artifacts from -# - a GitHub access token, see https://github.com/settings/tokens -# -# Usage: download-workflow-artifacts.sh - -WORKFLOW_RUN_ID=${WORKFLOW_RUN_ID:-$1} -GITHUB_TOKEN=${GITHUB_TOKEN:-$2} -GITHUB_API_VERSION=${GITHUB_API_VERSION:-2022-11-28} -GITHUB_API_URL=${GITHUB_API_URL:-https://api.github.com/repos/WebAssembly/wasi-sdk} -TMP_DIR=$(mktemp -d -t wasi-sdk-artifacts.XXXXXXX) - -if [ -z "${WORKFLOW_RUN_ID}" ] || [ -z "${GITHUB_TOKEN}" ]; then - >&2 echo "Missing parameter; exiting..." - >&2 echo "Usage: download-worfklow-artifacts.sh " - exit 1 -fi - -# List out the artifacts in the given workflow run. -# See https://docs.github.com/en/rest/actions/artifacts#list-workflow-run-artifacts -ARTIFACTS=$(curl \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${GITHUB_TOKEN}" \ - -H "X-GitHub-Api-Version: ${GITHUB_API_VERSION}" \ - "${GITHUB_API_URL}/actions/runs/${WORKFLOW_RUN_ID}/artifacts" \ - | jq -r '.artifacts[] | [(.id|tostring), .name, .archive_download_url] | join(",")') - -for A in $ARTIFACTS; do - ID=$(echo $A | cut -d ',' -f 1) - NAME=$(echo $A | cut -d ',' -f 2) - URL=$(echo $A | cut -d ',' -f 3) - TO=$TMP_DIR/$NAME.zip - # Exclude dist-ubuntu-latest to prefer dist-ubuntu-bionic, which is - # compatible with wider distributions. See: - # - https://github.com/WebAssembly/wasi-sdk/pull/273#issuecomment-1373879491 - # - https://github.com/WebAssembly/wasi-sdk/issues/303 - if [ "${NAME}" = "dist-ubuntu-latest" ]; then - continue - fi - # Exclude the 32-bit Windows artifact in favor of the 64-bit one. This helps - # ensure the identically-named 32-bit tarfile doesn't overwrite the 64-bit - # one below. See: - # - https://github.com/WebAssembly/wasi-sdk/issues/326 - if [ "${NAME}" = "dist-windows-latest-x86" ]; then - continue - fi - >&2 echo "===== Downloading: ${TO} =====" - - # Download the artifacts to the temporary directory. - # See https://docs.github.com/en/rest/actions/artifacts#download-an-artifact - curl \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${GITHUB_TOKEN}" \ - -H "X-GitHub-Api-Version: ${GITHUB_API_VERSION}" \ - --location --output "${TO}" \ - "${GITHUB_API_URL}/actions/artifacts/${ID}/zip" -done - -# Unzip the workflow artifacts into a `release` directory. -pushd $TMP_DIR > /dev/null -mkdir release -ls -1 *.zip | xargs -n1 unzip -q -o -d release -# Some explanation: -# -1 prints each file on a separate line -# -n1 runs the command once for each item -# -q means quietly -# -o allows unzip to overwrite existing files (e.g., multiple copies of `libclang_rt.builtins-wasm32-wasi-...`) -# -d tells unzip which directory to place things in ->&2 echo "===== Files to release: ${TMP_DIR}/release =====" ->&2 ls -1 release -popd > /dev/null - ->&2 echo ->&2 echo "Ensure the above artifacts look correct, then run \`draft-release.sh\` with the following directory:" -echo "${TMP_DIR}/release" diff --git a/ci/draft-release.sh b/ci/draft-release.sh deleted file mode 100755 index 905ecb9..0000000 --- a/ci/draft-release.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env bash -set -e - -# This script creates a draft pre-release with the artifacts produced in a -# workflow run (see `download-workflow-artifacts.sh`). Note that the pre-release -# is not published publicly--this is kept as a manual step as a safeguard. The -# script has several pre-requisites: -# - some standard Bash tools (curl, unzip) and one slightly more rare one (jq) -# - an already-created tag in the repository (this marks the code to release) -# - a directory containing the artifacts to attach to the release. -# - a GitHub access token, see https://github.com/settings/tokens -# -# Usage: draft-release.sh - -TAG=${TAG:-$1} -ARTIFACTS_DIR=${ARTIFACTS_DIR:-$2} -GITHUB_TOKEN=${GITHUB_TOKEN:-$3} -GITHUB_API_VERSION=${GITHUB_API_VERSION:-2022-11-28} -GITHUB_API_URL=${GITHUB_API_URL:-https://api.github.com/repos/WebAssembly/wasi-sdk} -TMP_DIR=$(mktemp -d -t release.sh.XXXXXXX) - -if [ -z "${TAG}" ] || [ -z "${ARTIFACTS_DIR}" ] || [ -z "${GITHUB_TOKEN}" ]; then - >&2 echo "Missing parameter; exiting..." - >&2 echo "Usage: draft-release.sh " - exit 1 -fi - -# Get the commit SHA for the passed tag. -# See https://docs.github.com/en/rest/commits/commits#get-a-commit -MATCHING_COMMIT=$(curl \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${GITHUB_TOKEN}" \ - -H "X-GitHub-Api-Version: ${GITHUB_API_VERSION}" \ - "${GITHUB_API_URL}/commits/${TAG}") -COMMIT=$(echo $MATCHING_COMMIT | jq -r '.sha') ->&2 echo "===== Found commit for tag ${TAG}: ${COMMIT} =====" - -# Create a draft pre-release for this commit. -# See https://docs.github.com/en/rest/releases/releases#create-a-release -RELEASE_JSON=$(curl \ - -X POST \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${GITHUB_TOKEN}"\ - -H "X-GitHub-Api-Version: ${GITHUB_API_VERSION}" \ - "${GITHUB_API_URL}/releases" \ - -d '{"tag_name":"'${TAG}'","target_commitish":"'${COMMIT}'","name":"'${TAG}'","draft":true,"prerelease":true,"generate_release_notes":true}') -UPLOAD_URL=$(echo $RELEASE_JSON | jq -r '.upload_url') -# Remove the "helpful" but invalid URL suffix that GitHub adds: -UPLOAD_URL=${UPLOAD_URL/\{?name,label\}} -HTML_URL=$(echo $RELEASE_JSON | jq -r '.html_url') ->&2 echo "===== Created draft release: ${HTML_URL} =====" - -# Upload the unzipped artifact files to the release. -# See https://docs.github.com/en/rest/releases/assets#upload-a-release-asset -for FILE in $(ls "${ARTIFACTS_DIR}"); do - FROM=$ARTIFACTS_DIR/$FILE - >&2 echo "===== Uploading: ${FROM} =====" - UPLOADED=$(curl \ - -X POST \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${GITHUB_TOKEN}"\ - -H "X-GitHub-Api-Version: ${GITHUB_API_VERSION}" \ - -H "Content-Type: application/octet-stream" \ - "${UPLOAD_URL}?name=${FILE}" \ - --data-binary "@${FROM}") -done - ->&2 echo ->&2 echo "===== Completed =====" ->&2 echo "This created a draft release, do not forget to manually publish it at:" -echo "${HTML_URL}" diff --git a/ci/get-workflows-for-tag.sh b/ci/get-workflows-for-tag.sh deleted file mode 100755 index 8792041..0000000 --- a/ci/get-workflows-for-tag.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env bash -set -e - -# This script retrieves a list of GitHub workflow runs that have successfully completed for a given -# Git tag. The list is printed to stdout (all other output to stderr). It has several -# pre-requisites: -# - some standard Bash tools (curl) and one slightly more rare one (jq) -# - an already-created tag in the repository (this marks the code to release) -# - a GitHub access token, see https://github.com/settings/tokens -# -# Usage: get-workflows-for-tag.sh - -TAG=${TAG:-$1} -GITHUB_TOKEN=${GITHUB_TOKEN:-$2} -GITHUB_API_VERSION=${GITHUB_API_VERSION:-2022-11-28} -GITHUB_API_URL=${GITHUB_API_URL:-https://api.github.com/repos/WebAssembly/wasi-sdk} - -if [ -z "${TAG}" ] || [ -z "${GITHUB_TOKEN}" ]; then - >&2 echo "Missing parameter; exiting..." - >&2 echo "Usage: get-workflows-for-tag.sh " - exit 1 -fi - -# Get the commit SHA for the passed tag. -# See https://docs.github.com/en/rest/commits/commits#get-a-commit -MATCHING_COMMIT=$(curl \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${GITHUB_TOKEN}" \ - -H "X-GitHub-Api-Version: ${GITHUB_API_VERSION}" \ - "${GITHUB_API_URL}/commits/${TAG}") -COMMIT=$(echo $MATCHING_COMMIT | jq -r '.sha') ->&2 echo "===== Found commit for tag ${TAG}: ${COMMIT} =====" - -# Find the workflow runs matching the tag commit. -# See https://docs.github.com/en/rest/actions/workflow-runs#list-workflow-runs-for-a-repository -MATCHING_WORKFLOWS=$(curl \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${GITHUB_TOKEN}" \ - -H "X-GitHub-Api-Version: ${GITHUB_API_VERSION}" \ - "${GITHUB_API_URL}/actions/runs?head_sha=${COMMIT}&status=success") -WORKFLOW_RUN_IDS=$(echo $MATCHING_WORKFLOWS | jq -r '.workflow_runs[].id') ->&2 echo "===== Matching workflow run IDs: =====" -echo "$WORKFLOW_RUN_IDS" diff --git a/ci/is-workflow-valid.sh b/ci/is-workflow-valid.sh deleted file mode 100755 index a7f0c80..0000000 --- a/ci/is-workflow-valid.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env bash -set -e - -# This script checks 1) that the workflow commit corresponds to the commit for -# the given tag and 2) that the workflow has completed. This is a sanity check -# to ensure the artifacts we are about to publish are in fact built from the -# commit/tag we think. The script has several pre-requisites: -# - some standard Bash tools (curl, unzip) and one slightly more rare one (jq) -# - an already-created tag in the repository (this marks the code to release) -# - the ID of a workflow run that has run successfully--this is where we -# retrieve the artifacts from -# - a GitHub access token, see https://github.com/settings/tokens -# -# Usage: is-workflow-valid.sh - -TAG=${TAG:-$1} -WORKFLOW_RUN_ID=${WORKFLOW_RUN_ID:-$2} -GITHUB_TOKEN=${GITHUB_TOKEN:-$3} -GITHUB_API_VERSION=${GITHUB_API_VERSION:-2022-11-28} -GITHUB_API_URL=${GITHUB_API_URL:-https://api.github.com/repos/WebAssembly/wasi-sdk} - -if [ -z "${TAG}" ] || [ -z "${WORKFLOW_RUN_ID}" ] || [ -z "${GITHUB_TOKEN}" ]; then - >&2 echo "Missing parameter; exiting..." - >&2 echo "Usage: is-workflow-valid.sh " - exit 1 -fi - -# Get the commit SHA for the passed tag. -# See https://docs.github.com/en/rest/commits/commits#get-a-commit -MATCHING_COMMIT=$(curl \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${GITHUB_TOKEN}" \ - -H "X-GitHub-Api-Version: ${GITHUB_API_VERSION}" \ - "${GITHUB_API_URL}/commits/${TAG}") -COMMIT=$(echo $MATCHING_COMMIT | jq -r '.sha') ->&2 echo "===== Found commit for tag ${TAG}: ${COMMIT} =====" - -# Check that the commit of the workflow run matches the tag commit and that the -# workflow was successful. -# See https://docs.github.com/en/rest/actions/workflow-runs#get-a-workflow-run -WORKFLOW_RUN=$(curl \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${GITHUB_TOKEN}" \ - -H "X-GitHub-Api-Version: ${GITHUB_API_VERSION}" \ - "${GITHUB_API_URL}/actions/runs/${WORKFLOW_RUN_ID}") -WORKFLOW_COMMIT=$(echo $WORKFLOW_RUN | jq -r '.head_sha') -WORKFLOW_STATUS=$(echo $WORKFLOW_RUN | jq -r '.status') ->&2 echo "===== Found commit for workflow ${WORKFLOW_RUN_ID}: ${WORKFLOW_COMMIT} =====" -if [ "${COMMIT}" != "${WORKFLOW_COMMIT}" ]; then - >&2 echo "Commit at tag ${TAG} did not match the commit for workflow ${WORKFLOW_RUN_ID}, exiting...:" - >&2 echo " ${COMMIT} != ${WORKFLOW_COMMIT}" - exit 1 -fi -if [ "${WORKFLOW_STATUS}" != "completed" ]; then - >&2 echo "Workflow ${WORKFLOW_RUN_ID} did not end successfully, exiting...:" - >&2 echo " status = ${WORKFLOW_STATUS}" - exit 1 -fi