Skip to content

Release

Release #47

Workflow file for this run

name: Release
on:
schedule:
# Run at 22:15 pm, daily.
# To make sure it finishes in time before next WPT daily epoch run
- cron: '15 22 * * *'
workflow_dispatch:
inputs:
# Note: On scheduled runs `inputs.regular_release` will be `null`, which allows us to create
# defaults by using `${{ inputs.regular_release || 'my_default_value' }}` expressions.
regular_release:
description: '`true` to create a release on this repo, false to release to the nightly-releases repo'
type: boolean
default: false
crates_io:
description: '`true` to publish to crates.io'
type: boolean
default: false
release_tag:
required: true
type: string
description: 'The tag to create for the release'
env:
RUST_BACKTRACE: 1
SHELL: /bin/bash
RELEASE_REPO: ${{ github.repository_owner }}/${{ inputs.regular_release && 'servo' || 'servo-nightly-builds' }}
jobs:
create-draft-release:
# This job is only useful when run on upstream servo.
if: github.repository == 'servo/servo' || github.event_name == 'workflow_dispatch'
name: Create Draft GH Release
runs-on: ubuntu-latest
environment: &publish-environment
name: publish
deployment: false
steps:
- id: create-release
run: |
if [[ "${{ inputs.release_tag }}" != "" ]]; then
RELEASE_TAG="${{ inputs.release_tag }}"
RELEASE_NOTES="Servo release ${{ inputs.release_tag }}"
else
RELEASE_TAG=$(date "+%F")
RELEASE_NOTES="Nightly build based on servo/servo@${{ github.sha }}"
fi
RELEASE_URL=$(gh release create "${RELEASE_TAG}" \
--draft \
--title "${RELEASE_TAG}" \
--notes "${RELEASE_NOTES}" \
--repo ${RELEASE_REPO})
TEMP_TAG=$(basename "$RELEASE_URL")
RELEASE_ID=$( \
gh api -H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2026-03-10" \
"/repos/${RELEASE_REPO}/releases/tags/${TEMP_TAG}" \
| jq '.id' \
)
echo "RELEASE_ID=${RELEASE_ID}" >> ${GITHUB_OUTPUT}
echo "RELEASE_TAG=${RELEASE_TAG}" >> ${GITHUB_OUTPUT}
env:
GITHUB_TOKEN: ${{ inputs.regular_release && github.token || secrets.NIGHTLY_REPO_TOKEN }}
outputs:
release-id: ${{ steps.create-release.outputs.RELEASE_ID }}
release-tag: ${{ steps.create-release.outputs.RELEASE_TAG }}
publish-nightly-release:
# We only auto-publish nightly releases, so we do not use this job for regular releases.
if: |
always()
&& (github.repository == 'servo/servo' || github.event_name == 'workflow_dispatch')
&& (inputs.regular_release || false) == false
name: Publish GH Release
runs-on: ubuntu-latest
environment: *publish-environment
steps:
- name: Publish release (success)
if: ${{ !contains(needs.*.result, 'failure') && (!contains(needs.*.result, 'cancelled') && !cancelled()) }}
env:
MAKE_LATEST: ${{ github.event_name == 'schedule' && 'true' || 'false' }}
run: |
gh api \
--method PATCH \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2026-03-10" \
/repos/${RELEASE_REPO}/releases/${RELEASE_ID} \
-F draft=false \
-f make_latest="${MAKE_LATEST}"
- name: Publish release (failure)
if: ${{ contains(needs.*.result, 'failure') || (contains(needs.*.result, 'cancelled') || cancelled()) }}
run: |
gh api \
--method PATCH \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2026-03-10" \
/repos/${RELEASE_REPO}/releases/${RELEASE_ID} \
-F prerelease=true \
-F draft=false \
-f make_latest=false
env:
GITHUB_TOKEN: ${{ inputs.regular_release && github.token || secrets.NIGHTLY_REPO_TOKEN }}
RELEASE_ID: ${{ needs.create-draft-release.outputs.release-id }}
needs:
- create-draft-release
- upload-vendored-source
- upload-artifacts-nightly
- upload-artifacts-release
publish-crates-io:
name: 'Publish to crates.io'
if: github.repository == 'servo/servo' && (inputs.crates_io || false)
environment:
name: publish_crates_io
deployment: false
runs-on: ubuntu-22.04
permissions:
id-token: write
steps:
- uses: actions/checkout@v6
- uses: rust-lang/crates-io-auth-action@v1
id: auth
- name: Publish to crates.io
env:
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
SERVO_CRATES_IO_SLEEP_AFTER_PUBLISH_SECONDS: "30"
SERVO_CRATES_IO_VERIFY_PUBLISHED_TIMEOUT_SECONDS: "300"
SERVO_CRATES_IO_VERIFY_PUBLISHED_INTERVAL_SECONDS: "10"
# Verification requires building, which is incredibly slow and also increases our attack surface.
# If we decide for an extra verification, we should add a seperate job before this one, which
# does a `dry-run` publish without any elevated permissions.
run: |
python3 etc/ci/publish_crates_io.py --no-verify
build-win:
# This job is only useful when run on upstream servo.
if: github.repository == 'servo/servo' || github.event_name == 'workflow_dispatch'
name: Build production release (Windows)
uses: ./.github/workflows/windows.yml
with:
profile: "production"
upload_zip: true
force-github-hosted-runner: true # <https://github.com/servo/servo/issues/33296>
upload-vendored-source:
# This job is only useful when run on upstream servo.
if: github.repository == 'servo/servo' || github.event_name == 'workflow_dispatch'
name: Upload vendored source archive
runs-on: ubuntu-latest
environment: *publish-environment
permissions:
contents: write
id-token: write
attestations: write
env:
ARTIFACT_BASENAME: "servo-${{ needs.create-draft-release.outputs.release-tag }}-src-vendored"
ARTIFACT_FILENAME: "servo-${{ needs.create-draft-release.outputs.release-tag }}-src-vendored.tar.gz"
needs:
- create-draft-release
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
- name: Generate vendored archive
run: |
python3 etc/vendor_servo.py --filename "${ARTIFACT_BASENAME}"
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v3
with:
subject-path: ${{ env.ARTIFACT_FILENAME }}
- name: Upload vendored archive to release
run: |
gh release upload "${{ needs.create-draft-release.outputs.release-tag }}" \
"${ARTIFACT_FILENAME}" \
--repo "${RELEASE_REPO}"
env:
GITHUB_TOKEN: ${{ inputs.regular_release && github.token || secrets.NIGHTLY_REPO_TOKEN }}
upload-artifacts-nightly:
# Only run scheduled nightly builds on upstream servo.
if: |
(github.repository == 'servo/servo' || github.event_name == 'workflow_dispatch')
&& (inputs.regular_release || false) == false
runs-on: ubuntu-latest
permissions:
id-token: write
attestations: write
environment: *publish-environment
needs: &upload-artifacts-needs
- create-draft-release
- build-win
- build-mac
- build-mac-arm64
- build-linux
- build-android
- build-ohos
strategy: &upload-artifacts-strategy
fail-fast: false
matrix:
include:
- artifact_ids: ${{ needs.build-win.outputs.artifact_ids }}
artifact_platform: windows-msvc
- artifact_ids: ${{ needs.build-mac.outputs.artifact_ids }}
artifact_platform: mac
- artifact_ids: ${{ needs.build-mac-arm64.outputs.artifact_ids }}
artifact_platform: mac-arm64
- artifact_ids: ${{ needs.build-linux.outputs.artifact_ids }}
artifact_platform: linux
- artifact_ids: ${{ needs.build-android.outputs.artifact_ids }}
artifact_platform: android
- artifact_ids: ${{ needs.build-ohos.outputs.artifact_ids }}
artifact_platform: ohos
env:
ARTIFACT_IDS: ${{ matrix.artifact_ids }}
ARTIFACT_PLATFORM: ${{ matrix.artifact_platform }}
GITHUB_RELEASE_ID: ${{ needs.create-draft-release.outputs.release-id }}
RELEASE_REPO: ${{ github.repository_owner }}/servo-nightly-builds
RELEASE_REPO_TOKEN: ${{ secrets.NIGHTLY_REPO_TOKEN }}
S3_UPLOAD_CREDENTIALS: ${{ secrets.S3_UPLOAD_CREDENTIALS }}
steps: &upload-artifacts-steps
- uses: actions/checkout@v6
with:
sparse-checkout: |
.github
etc/ci
fetch-depth: '1'
- name: Setup Python
uses: ./.github/actions/setup-python
- name: Validate artifact IDs
run: |
if [[ -z "${ARTIFACT_IDS}" ]]; then
echo "Error: No artifact IDs provided."
echo "Help: Check the build job's outputs.artifact_ids value."
echo "If you recently renamed the build job without updating the corresponding output reference,"
echo "that is likely the cause of this error."
exit 1
fi
- uses: actions/download-artifact@v8
with:
artifact-ids: ${{ env.ARTIFACT_IDS }}
merge-multiple: true
path: release-artifacts
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v3
with:
subject-path: 'release-artifacts/*'
- name: Upload release artifacts
run: |
./etc/ci/upload_nightly.py "${ARTIFACT_PLATFORM}" \
--secret-from-environment \
--github-release-id "${GITHUB_RELEASE_ID}" \
release-artifacts/*
upload-artifacts-release:
if: github.event_name == 'workflow_dispatch' && inputs.regular_release
runs-on: ubuntu-latest
environment: *publish-environment
permissions:
id-token: write
attestations: write
# Necessary for the github token to upload artifacts to the release.
contents: write
needs: *upload-artifacts-needs
strategy: *upload-artifacts-strategy
env:
ARTIFACT_IDS: ${{ matrix.artifact_ids }}
ARTIFACT_PLATFORM: ${{ matrix.artifact_platform }}
GITHUB_RELEASE_ID: ${{ needs.create-draft-release.outputs.release-id }}
RELEASE_REPO: ${{ github.repository_owner }}/servo
RELEASE_REPO_TOKEN: ${{ github.token }}
S3_UPLOAD_CREDENTIALS: ${{ secrets.S3_UPLOAD_CREDENTIALS }}
steps: *upload-artifacts-steps
build-mac:
# This job is only useful when run on upstream servo.
if: github.repository == 'servo/servo' || github.event_name == 'workflow_dispatch'
name: Build production release (macOS)
uses: ./.github/workflows/mac.yml
with:
profile: "production"
force-github-hosted-runner: true # <https://github.com/servo/servo/issues/33296>
build-mac-arm64:
# This job is only useful when run on upstream servo.
if: github.repository == 'servo/servo' || github.event_name == 'workflow_dispatch'
name: Build production release (macOS Arm64)
uses: ./.github/workflows/mac-arm64.yml
with:
profile: "production"
force-github-hosted-runner: true # <https://github.com/servo/servo/issues/33296>
build-linux:
# This job is only useful when run on upstream servo.
if: github.repository == 'servo/servo' || github.event_name == 'workflow_dispatch'
name: Build production release (Linux)
uses: ./.github/workflows/linux.yml
with:
profile: "production"
force-github-hosted-runner: true # <https://github.com/servo/servo/issues/33296>
build-android:
# This job is only useful when run on upstream servo.
if: github.repository == 'servo/servo' || github.event_name == 'workflow_dispatch'
name: Build release (Android)
uses: ./.github/workflows/android.yml
with:
profile: "release"
secrets: inherit
build-ohos:
# This job is only useful when run on upstream servo.
if: github.repository == 'servo/servo' || github.event_name == 'workflow_dispatch'
name: Build production release (OpenHarmony)
uses: ./.github/workflows/ohos.yml
with:
profile: "production"
upload_library: true
secrets: inherit