Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c462909
Move nightly-docgen.yml, nightly-regression-report.yml to this reposi…
marcelolynch Mar 6, 2026
506e9eb
Incorporate changes from Anne's PR
marcelolynch Mar 6, 2026
6e9ad67
step
marcelolynch Mar 6, 2026
f5605f5
step
marcelolynch Mar 6, 2026
8966673
step
marcelolynch Mar 6, 2026
7e01f4d
change api key variable
marcelolynch Mar 9, 2026
2ab44c8
fix: Fix quoting in env variables
marcelolynch Mar 9, 2026
47a8ad8
Correct email
marcelolynch Mar 9, 2026
b001c66
feat: fast GitHub App token minting via Azure Key Vault signing (#6)
marcelolynch Mar 10, 2026
65845ae
feat: Add action to mint Azure Storage token (#3)
marcelolynch Mar 10, 2026
e1a6b46
fix: Set pipefail in scripts that pipe builds to tee (#12)
marcelolynch Mar 10, 2026
780354b
fix: handle Zulip rate limits in emoji reactions script (#8)
kim-em Mar 23, 2026
3f60a05
fix: handle missing nightly-testing branch in merge script (#14)
kim-em Mar 23, 2026
6ea192e
fix: report full backward.* option names in tech debt metrics (#15)
kim-em Mar 23, 2026
00cad20
fix: `declarations_diff.sh` can't handle `public` modifier (#16)
Komyyy Apr 1, 2026
cf9e1ba
fix: configure nightly-testing remote in merge script (#18)
kim-em Apr 17, 2026
99c977a
chore: drop info message counts from Zulip build report (#19)
kim-em Apr 17, 2026
2b306fb
fix: look up existing lean-pr-testing comments under the current bot …
kim-em Apr 17, 2026
e9b62bc
docs: actionable instructions for running tech debt script locally (#22)
kim-em Apr 21, 2026
6498947
fix(verify_commits.sh): replay auto commits in isolated worktrees, su…
bryangingechen Apr 27, 2026
7f761b0
feat(olean_diff.py): script for comparing oleans (#24)
bryangingechen Apr 27, 2026
779b281
feat: report number of `@[expose]`d public sections as tech debt (#25)
Vierkantor Apr 27, 2026
a30f1a2
fix local run instructions (#27)
justus-springer Apr 28, 2026
2abe103
feat: make printing info optional for zulip_build_report.sh (#23)
chenson2018 Apr 28, 2026
73c3f95
feat: add tech debt counter for disabled varHead simp warnings (#21)
kim-em Apr 28, 2026
abd4812
fix: require all CI outcomes to succeed before adding `builds-mathlib…
kim-em May 4, 2026
0a291be
feat: classify tech debt into weak and strong (#28)
Vierkantor May 4, 2026
6d26b57
chore: temporarily mark disabled deprecation lints as weak tech debt …
Vierkantor May 4, 2026
59c190c
fix: surface curl HTTP errors in lean-pr-testing-comments.sh (#32)
kim-em May 5, 2026
2e0abed
chore: route Zulip notifications to nightly-testing-mathlib (#33)
kim-em May 5, 2026
9d32c90
fix: tolerate 404 in `remove_label` in lean-pr-testing-comments.sh (#34)
kim-em May 5, 2026
6cee591
fix: filter tech debt rows by level using a literal pipe (#36)
kim-em May 11, 2026
ddf6267
chore: use `git switch --detach` when checking out a commit hash (#35)
Vierkantor May 13, 2026
3c72af0
feat: orchestrator for the mathlib4 cross-reference tag review bot
kim-em May 22, 2026
b77378e
refactor(crossref_review): consume TSV from mathlib4's post-build lin…
kim-em May 22, 2026
78c7a68
fix(crossref_review): harden Markdown escaping for PR-author input
kim-em May 22, 2026
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
77 changes: 77 additions & 0 deletions .github/actions/azure-create-cache-token/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: Azure Create Cache Token
description: Mint an Azure storage access token via GitHub OIDC for cache uploads.

inputs:
azure-client-id:
description: Azure user-assigned managed identity or app registration client ID.
required: true
azure-tenant-id:
description: Azure tenant ID.
required: true

runs:
using: composite
steps:
- name: Azure CLI OIDC login and mint storage bearer token
shell: bash
env:
CLIENT_ID: ${{ inputs.azure-client-id }}
TENANT_ID: ${{ inputs.azure-tenant-id }}
run: |
# OIDC audience required by Azure AD workload identity federation.
AUDIENCE='api://AzureADTokenExchange'
# Azure Storage resource used when minting the cache bearer token.
RESOURCE='https://storage.azure.com/'

if [ -z "$CLIENT_ID" ] || [ -z "$TENANT_ID" ]; then
echo "Missing azure-client-id or azure-tenant-id"
exit 1
fi

# This variable is provided by GitHub automatically in OIDC-enabled actions,
# see https://docs.github.com/en/actions/how-tos/secure-your-work/security-harden-deployments/oidc-in-cloud-providers#using-custom-actions
OIDC_URL="$ACTIONS_ID_TOKEN_REQUEST_URL"

# Preserve existing query params and append the audience selector.
if [[ "$OIDC_URL" == *\?* ]]; then
OIDC_URL="${OIDC_URL}&audience=${AUDIENCE}"
else
OIDC_URL="${OIDC_URL}?audience=${AUDIENCE}"
fi

# Exchange GitHub's request token for an OIDC JWT scoped to the Azure audience.
OIDC_TOKEN="$(
curl --silent --show-error \
-H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \
"$OIDC_URL" | python3 -c 'import json,sys; print(json.load(sys.stdin)["value"])'
)"

az login \
--service-principal \
--username "$CLIENT_ID" \
--tenant "$TENANT_ID" \
--federated-token "$OIDC_TOKEN" \
--allow-no-subscriptions \
--output none

if MATHLIB_CACHE_AZURE_BEARER_TOKEN_RAW="$(az account get-access-token --resource "$RESOURCE" --query accessToken -o tsv)"; then
# `az ... -o tsv` can include trailing whitespace; trim it before validation/export.
MATHLIB_CACHE_AZURE_BEARER_TOKEN="${MATHLIB_CACHE_AZURE_BEARER_TOKEN_RAW%"${MATHLIB_CACHE_AZURE_BEARER_TOKEN_RAW##*[![:space:]]}"}"
if [ -z "$MATHLIB_CACHE_AZURE_BEARER_TOKEN" ]; then
echo "Minted Azure storage bearer token is empty"
exit 1
fi
# Mask token in all subsequent logs emitted by this job.
echo "::add-mask::$MATHLIB_CACHE_AZURE_BEARER_TOKEN"
MATHLIB_CACHE_AZURE_BEARER_TOKEN_EXPIRES_ON="$(az account get-access-token --resource "$RESOURCE" --query expiresOn -o tsv 2>/dev/null || true)"
if [ -n "$MATHLIB_CACHE_AZURE_BEARER_TOKEN_EXPIRES_ON" ]; then
echo "cache_bearer_expires_on=$MATHLIB_CACHE_AZURE_BEARER_TOKEN_EXPIRES_ON"
else
echo "cache_bearer_expires_on=unavailable"
fi
# Export for downstream workflow steps in this job.
echo "MATHLIB_CACHE_AZURE_BEARER_TOKEN=$MATHLIB_CACHE_AZURE_BEARER_TOKEN" >> "$GITHUB_ENV"
else
echo "Failed to mint Azure storage bearer token"
exit 1
fi
102 changes: 102 additions & 0 deletions .github/actions/azure-create-github-app-token/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Azure Create GitHub App Token

```text
GitHub Actions job
|
| (1) Request OIDC token (aud = api://AzureADTokenExchange)
v
GitHub OIDC endpoint
|
| OIDC JWT
v
mint_token.py
|
| (2) Exchange OIDC JWT for Entra access token
`-----------,
\
|
|
v
Microsoft Entra token endpoint
|
| access_token (scope: https://vault.azure.net/.default)
|
,------------
|
|(3) Key Vault sign API with non-exportable key
|
`----------->
|
|
v
Azure Key Vault
|
| RSA signature over GitHub App JWT signing input digest
|
,------------
|
| (4) Signed GitHub App JWT -> mint installation token
|
`-----------,
|
|
v
GitHub API
|
,-----------'
|
| (5) Write masked outputs
|
v
Action outputs (`token`, `installation-id`)
```

This local composite action mints a GitHub App installation token without storing the app private key in GitHub Secrets.

## Components

- `action.yml`: action interface (inputs/outputs) and execution wiring.
- `mint_token.py`: end-to-end token flow:
- build GitHub App JWT payload/header,
- fetch GitHub OIDC token,
- exchange OIDC token for Azure access token,
- call Key Vault `sign`,
- exchange signed app JWT for GitHub installation token.
- Azure Key Vault key: non-exportable RSA key used only for signing.
- Federated credential in Entra: allows this workflow identity to exchange GitHub OIDC token.

## Avoiding `azure/login`

With `azure/login` + `az keyvault key sign`, startup/login overhead dominates runtime (about 20-30s). For this action we only need one Key Vault data-plane call (`sign`), so pulling in CLI login is unnecessary.

The current implementation uses direct HTTPS calls for the exact same auth chain, with less runtime overhead.

## Inputs used

- `app-id`
- `key-vault-name`
- `key-name`
- `key-version` (optional)
- `azure-client-id`
- `azure-tenant-id`
- `owner` (optional)
- `repositories` (optional)
- `jwt-expiration-seconds` (optional, default: `540`)

## Fixed defaults

The action intentionally hard-codes the following values:

- OIDC audience: `api://AzureADTokenExchange`
- GitHub API URL: `https://api.github.com`

When optional inputs are omitted:

- Key Vault key version: latest (`/keys/{key-name}/sign`)
- Installation resolution: current repository (`GITHUB_REPOSITORY`)
- Installation token scope: full installation permissions (no repository filter)

## Security notes
- Workflow must grant `permissions: id-token: write` to allow this action to request a GitHub OIDC token for Entra token exchange.
- Remember keeping Entra federated credential scope tight (repo/workflow/ref constraints).
- Limit Key Vault permissions to the minimum required (`keys/sign` on the target key).
61 changes: 61 additions & 0 deletions .github/actions/azure-create-github-app-token/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Azure Create GitHub App Token
description: Mint a GitHub App installation token by signing the app JWT with an Azure Key Vault key.

inputs:
app-id:
description: GitHub App ID.
required: true
key-vault-name:
description: Azure Key Vault name containing the signing key.
required: true
key-name:
description: Azure Key Vault key name used to sign the JWT.
required: true
key-version:
description: Optional Azure Key Vault key version.
required: false
default: ""
azure-client-id:
description: Azure app registration application (client) ID.
required: true
azure-tenant-id:
description: Azure tenant ID.
required: true
owner:
description: Optional GitHub organization/user owner to resolve installation from.
required: false
default: ""
repositories:
description: Optional comma or newline separated repository names for token scoping.
required: false
default: ""
jwt-expiration-seconds:
description: JWT lifetime in seconds (must be <= 600).
required: false
default: "540"

outputs:
token:
description: GitHub App installation access token.
value: ${{ steps.mint.outputs.token }}
installation-id:
description: GitHub App installation ID.
value: ${{ steps.mint.outputs.installation-id }}

runs:
using: composite
steps:
- name: Mint installation token
id: mint
shell: bash
env:
INPUT_APP_ID: ${{ inputs.app-id }}
INPUT_KEY_VAULT_NAME: ${{ inputs.key-vault-name }}
INPUT_KEY_NAME: ${{ inputs.key-name }}
INPUT_KEY_VERSION: ${{ inputs.key-version }}
INPUT_AZURE_CLIENT_ID: ${{ inputs.azure-client-id }}
INPUT_AZURE_TENANT_ID: ${{ inputs.azure-tenant-id }}
INPUT_OWNER: ${{ inputs.owner }}
INPUT_REPOSITORIES: ${{ inputs.repositories }}
INPUT_JWT_EXPIRATION_SECONDS: ${{ inputs.jwt-expiration-seconds }}
run: python3 "${GITHUB_ACTION_PATH}/mint_token.py"
Loading