Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,9 @@ jobs:
name: Build - Documentation website

steps:
- name: Setup Git user
uses: mcanouil/quarto-workflows/.github/actions/setup-git-user@main
id: setup-git-user
with:
# Pull requests from forks cannot read the app key, so fall back to
# the workflow token there; nothing is pushed from this workflow.
gh-app-id: ${{ github.event_name != 'pull_request' && vars.APP_ID || '' }}
app-key: ${{ secrets.APP_KEY }}
gh-token: ${{ secrets.GITHUB_TOKEN }}

- name: Checkout repository
uses: actions/checkout@v7
with:
token: ${{ steps.setup-git-user.outputs.token }}
# Publish the default branch whatever the trigger: a release runs
# against its tag, which predates the quarto check transcripts that
# land on the default branch afterwards. Pull requests keep the
Expand Down
79 changes: 27 additions & 52 deletions .github/workflows/devcontainer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ jobs:
id: image_version
run: |
if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
echo "VERSION=${GITHUB_REF_NAME}" >> ${GITHUB_OUTPUT}
echo "VERSION=${GITHUB_REF_NAME}" >> "${GITHUB_OUTPUT}"
else
echo "VERSION=$(git rev-parse --short HEAD)" >> ${GITHUB_OUTPUT}
echo "VERSION=$(git rev-parse --short HEAD)" >> "${GITHUB_OUTPUT}"
fi

- name: Build and run Dev Container on release
Expand Down Expand Up @@ -135,7 +135,7 @@ jobs:
echo '```'
echo ""
echo "</details>"
) >>${GITHUB_STEP_SUMMARY}
) >> "${GITHUB_STEP_SUMMARY}"

- name: Save quarto check output
env:
Expand Down Expand Up @@ -235,35 +235,21 @@ jobs:
TARGET_FILE: docs/reference/quarto-check.qmd

steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Get the App token
id: token
uses: mcanouil/release-actions/token@v1
with:
persist-credentials: true
app-id: ${{ vars.APP_ID }}
app-key: ${{ secrets.APP_KEY }}
require-app: true

- name: Update branch
run: |
git fetch --all
git checkout main
git pull origin main

- name: Create GitHub App token
uses: actions/create-github-app-token@v3
id: app-token
# A release runs on its tag, so check out the default branch, where the
# transcripts land.
- name: Checkout repository
uses: actions/checkout@v7
with:
client-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_KEY }}

- name: Get GitHub App User ID
id: get-user-id
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"

- name: Git Config
run: |
git config --global user.name '${{ steps.app-token.outputs.app-slug }}[bot]'
git config --global user.email '${{ steps.get-user-id.outputs.user-id }}+${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com'
ref: ${{ github.event.repository.default_branch }}
token: ${{ steps.token.outputs.token }}

- name: Download quarto check outputs
uses: actions/download-artifact@v8
Expand Down Expand Up @@ -353,28 +339,17 @@ jobs:
update_docs_section "release" "/tmp/quarto-check-outputs/quarto-check-release-amd64/release.txt" "${BUILD_URL}"
update_docs_section "prerelease" "/tmp/quarto-check-outputs/quarto-check-prerelease-amd64/prerelease.txt" "${BUILD_URL}"

- name: Commit and push changes
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
BRANCH: "ci/update-quarto-check-docs"
COMMIT: "ci: update quarto check outputs in documentation"
run: |
if git show-ref --quiet refs/heads/${BRANCH}; then
echo "Branch ${BRANCH} already exists."
git branch -D "${BRANCH}"
git push origin --delete "${BRANCH}"
fi

git checkout -b "${BRANCH}"

git add "${TARGET_FILE}" || echo "No changes to add"
git commit -m "${COMMIT}" || echo "No changes to commit"
git push --force origin ${BRANCH} || echo "No changes to push"

sleep 5
gh pr create --fill-first --base "main" --head "${BRANCH}" --label "Type: CI/CD :robot:"
sleep 2
gh pr merge --auto --squash --delete-branch
- name: Land the transcripts
uses: mcanouil/release-actions/land@v1
with:
mode: pull-request
files: ${{ env.TARGET_FILE }}
base: ${{ github.event.repository.default_branch }}
message: "ci: update quarto check outputs in documentation"
branch: ci/update-quarto-check-docs
wait: false
allow-unchanged: true
token: ${{ steps.token.outputs.token }}

list-versions:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -462,7 +437,7 @@ jobs:
ALL_TAGS="${BASE_TAGS},${TAGS_WITH_BUILD}"
echo "All tags: ${ALL_TAGS}"
echo "::endgroup::"
echo "IMAGE_TAG=${ALL_TAGS}" >> ${GITHUB_OUTPUT}
echo "IMAGE_TAG=${ALL_TAGS}" >> "${GITHUB_OUTPUT}"

- name: Build and run Dev Container on release
uses: devcontainers/ci@v0.3
Expand Down
64 changes: 11 additions & 53 deletions .github/workflows/quarto-extensions-updater.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,60 +9,18 @@ on:
schedule:
- cron: 00 12 1 * *

concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref_name }}
cancel-in-progress: true
permissions:
contents: read

jobs:
quarto-extensions-updates:
runs-on: ubuntu-latest
updates:
uses: mcanouil/quarto-workflows/.github/workflows/quarto-extensions-updates.yml@v2
secrets: inherit
permissions:
contents: read
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v7

- name: Create GitHub App token
uses: actions/create-github-app-token@v3
id: app-token
with:
client-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_KEY }}

- name: Get GitHub App User ID
id: get-user-id
if: ${{ steps.app-token.outputs.app-slug != '' }}
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
APP_SLUG: ${{ steps.app-token.outputs.app-slug }}
run: |
echo "user-id=$(gh api "/users/${APP_SLUG}[bot]" --jq .id)" >> "${GITHUB_OUTPUT}"

- name: Configure Environment for Git User
env:
APP_SLUG: ${{ steps.app-token.outputs.app-slug }}
USER_ID: ${{ steps.get-user-id.outputs.user-id }}
run: |
if [ -z "${APP_SLUG}" ]; then
USER_NAME="github-actions[bot]"
USER_EMAIL="41898282+github-actions[bot]@users.noreply.github.com"
else
USER_NAME="${APP_SLUG}[bot]"
USER_EMAIL="${USER_ID}+${APP_SLUG}[bot]@users.noreply.github.com"
fi
git config --global user.name "${USER_NAME}"
git config --global user.email "${USER_EMAIL}"

- name: Setup Quarto
uses: quarto-dev/quarto-actions/setup@v2
with:
version: "pre-release"

- name: Update Quarto extensions
uses: mcanouil/quarto-extensions-updater@v2.2.1
with:
github-token: ${{ steps.app-token.outputs.token }}
pr-labels: "Type: Dependencies :arrow_up:"
group-updates: true
scan-directories: |
docs
with:
gh-app-id: ${{ vars.APP_ID }}
quarto-version: pre-release
scan-directories: |
docs
85 changes: 21 additions & 64 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,44 +19,36 @@ jobs:
timeout-minutes: 15

steps:
- name: Refuse to release from anything but the default branch
if: ${{ github.ref_name != github.event.repository.default_branch }}
env:
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
REF_NAME: ${{ github.ref_name }}
shell: bash
run: |
echo "::error::Releases are cut from ${DEFAULT_BRANCH}, not ${REF_NAME}."
exit 1

# The App only, with no fallback token: the default token cannot pass the
# pull request rule of the default branch, and a release it creates
# triggers neither the image build nor the documentation deploy.
- name: Setup Git User
uses: mcanouil/quarto-workflows/.github/actions/setup-git-user@v2
id: setup-git-user
- name: Get the App token
id: token
uses: mcanouil/release-actions/token@v1
with:
gh-app-id: ${{ vars.APP_ID }}
app-id: ${{ vars.APP_ID }}
app-key: ${{ secrets.APP_KEY }}
require-app: true

- name: Checkout repository
uses: actions/checkout@v7
with:
token: ${{ steps.setup-git-user.outputs.token }}
token: ${{ steps.token.outputs.token }}
# The whole history and every tag, since the same-day suffix is
# resolved from the tags already cut.
fetch-depth: 0

# The first release of a day is the bare date; every further one carries
# the count of releases cut that day, such as `2026.10.16-2`. An empty
# Unreleased section in CHANGELOG.md stops the release here.
# the count of releases cut that day, such as `2026.10.16-2`, and is
# titled with it, such as `2026-10-16 (2)`. An empty Unreleased section in
# CHANGELOG.md stops the release here.
- name: Bump the version
id: bump
uses: mcanouil/release-actions/bump@v1
with:
bump: calver
version-source: tag
token: ${{ steps.setup-git-user.outputs.token }}
token: ${{ steps.token.outputs.token }}
targets: |
- file: CITATION.cff
pattern: '^version: {version}$'
Expand All @@ -66,46 +58,22 @@ jobs:
# The App is exempt from the pull request rule of the default branch, and
# [skip ci] keeps CI from running again on a tree it has checked.
- name: Push the version
id: push
env:
VERSION: ${{ steps.bump.outputs.version }}
FILES: ${{ steps.bump.outputs.files }}
shell: bash
run: |
set -euo pipefail
printf '%s\n' "${FILES}" | git add --pathspec-from-file=-
git commit -m "ci: release ${VERSION} [skip ci]"
if ! git push origin "HEAD:refs/heads/${GITHUB_REF_NAME}"; then
echo "::error::The App could not push the bump to ${GITHUB_REF_NAME}. If the push output says the branch moved, dispatch this workflow again; otherwise add the App to the bypass list of the branch ruleset first."
exit 1
fi
echo "sha=$(git rev-parse HEAD)" >> "${GITHUB_OUTPUT}"
id: land
uses: mcanouil/release-actions/land@v1
with:
mode: push
files: ${{ steps.bump.outputs.files }}
version: ${{ steps.bump.outputs.version }}

- name: Compose the release body
id: notes
uses: mcanouil/release-actions/notes@v1
with:
notes-file: ${{ steps.bump.outputs.notes-file }}
tag: ${{ steps.bump.outputs.version }}
target: ${{ steps.push.outputs.sha }}
target: ${{ steps.land.outputs.sha }}
generate-notes: true
token: ${{ steps.setup-git-user.outputs.token }}

# A further release of a day is titled with its count, such as
# `2026-10-16 (2)`.
- name: Resolve the release title
id: title
env:
VERSION: ${{ steps.bump.outputs.version }}
DATE: ${{ steps.bump.outputs.date }}
shell: bash
run: |
set -euo pipefail
TITLE="${DATE}"
if [[ "${VERSION}" == *-* ]]; then
TITLE="${DATE} (${VERSION##*-})"
fi
echo "title=${TITLE}" >> "${GITHUB_OUTPUT}"
token: ${{ steps.token.outputs.token }}

# Created as the App, so that the published release starts the image
# build and the documentation deploy.
Expand All @@ -114,18 +82,7 @@ jobs:
with:
version: ${{ steps.bump.outputs.version }}
body-file: ${{ steps.notes.outputs.body-file }}
title: ${{ steps.title.outputs.title }}
target: ${{ steps.push.outputs.sha }}
title: "{date}{count}"
target: ${{ steps.land.outputs.sha }}
latest: true
token: ${{ steps.setup-git-user.outputs.token }}

# A new dispatch would stop on the emptied Unreleased section, so the
# pushed bump has to go first.
- name: Explain the recovery
if: ${{ failure() && steps.push.outputs.sha != '' }}
env:
VERSION: ${{ steps.bump.outputs.version }}
SHA: ${{ steps.push.outputs.sha }}
shell: bash
run: |
echo "::error::${GITHUB_REF_NAME} holds the bump ${SHA} for ${VERSION}, but the release failed. Create release ${VERSION} on ${SHA} by hand, or revert that commit with a pull request and dispatch this workflow again."
token: ${{ steps.token.outputs.token }}
Loading