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
88 changes: 88 additions & 0 deletions .github/workflows/ci-trusted.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: 🏷️ PR labels & reports

# ─────────────────────────────────────────────────────────────────────────────
# This workflow runs trusted-only operations that need write access to the PR
# (labeling, commenting, publishing test reports).
#
# SECURITY: uses pull_request_target which runs in the BASE branch context
# with access to secrets and write tokens. It must NEVER checkout or execute
# code from the fork — only use metadata and artifacts.
# ─────────────────────────────────────────────────────────────────────────────

on:
pull_request_target:
types: [opened, reopened, synchronize, labeled, unlabeled]

permissions:
contents: read
pull-requests: write

Comment on lines +16 to +19
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
labels:
name: PR labels
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout base branch (trusted code only)
timeout-minutes: 5
uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.base.ref }}

- name: Add labels
timeout-minutes: 5
uses: actions/labeler@v6

- name: Enforce labels
timeout-minutes: 5
uses: mheap/github-action-required-labels@v5
with:
mode: minimum
count: 1
labels: |
documentation
ci
sources
dependencies
submodules
add_comment: true

test-reports:
name: publish test reports
runs-on: ubuntu-latest
timeout-minutes: 10
# Wait for the CI workflow to complete so the artifact is available
if: github.event.action == 'synchronize' || github.event.action == 'opened'
steps:
- name: Wait for CI workflow
timeout-minutes: 5
uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.event.pull_request.head.sha }}
check-name: "lint & test"
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 30
Comment on lines +63 to +68

- name: Download test results artifact
timeout-minutes: 5
uses: actions/download-artifact@v4
with:
name: test-results
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
continue-on-error: true

- name: Publish test reports
timeout-minutes: 5
if: hashFiles('tests/.tests.xml') != ''
uses: pmeier/pytest-results-action@v0.8.0
with:
path: tests/.tests.xml
title: Test results
summary: true
display-options: fEX
fail-on-empty: false
104 changes: 49 additions & 55 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,59 +6,30 @@ on:
- main
pull_request:

permissions:
id-token: write
contents: write
actions: write
pull-requests: write
pages: write

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
# ──────────────────────────────────────────────────────────────────
# Lint & Test — runs for EVERY PR (including forks)
# Uses GitHub-hosted runners so untrusted code never touches infra.
# Minimal permissions: read-only token, no secrets.
# ──────────────────────────────────────────────────────────────────
ci:
name: continuous integration
runs-on: public-ledgerhq-shared-small
runs-on: ubuntu-latest
timeout-minutes: 60
permissions:
contents: read
steps:

- name: Checkout
timeout-minutes: 10
uses: actions/checkout@v7
with:
fetch-depth: 0
submodules: "recursive"

- name: Pull request | Add labels
timeout-minutes: 30
if: github.event_name == 'pull_request'
uses: actions/labeler@v6

- name: Pull request | Enforce labels
timeout-minutes: 5
if: github.event_name == 'pull_request'
uses: mheap/github-action-required-labels@v5
with:
mode: minimum
count: 1
labels: |
documentation
ci
sources
dependencies
submodules
add_comment: true

- name: Get API keys
timeout-minutes: 10
shell: bash
run: |
cat << EOF | jq -r 'to_entries[] | select(.key|endswith("_API_KEY")) | "\(.key)=\(.value)"' >> "$GITHUB_ENV"
${{ toJSON(secrets) }}
EOF

- name: Setup pre-commit cache
timeout-minutes: 10
uses: actions/cache@v5
Expand All @@ -74,6 +45,15 @@ jobs:
timeout-minutes: 10
run: pdm install --dev --check --frozen-lockfile

- name: Get API keys
timeout-minutes: 10
if: github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'push'
shell: bash
run: |
cat << EOF | jq -r 'to_entries[] | select(.key|endswith("_API_KEY")) | "\(.key)=\(.value)"' >> "$GITHUB_ENV"
${{ toJSON(secrets) }}
Comment thread
fsamier marked this conversation as resolved.
Dismissed
EOF

- name: Lint
timeout-minutes: 10
run: pdm run lint
Expand All @@ -84,43 +64,57 @@ jobs:
timeout-minutes: 40
run: pdm run test

- name: Publish test reports
- name: Upload test results
timeout-minutes: 10
if: ${{ !cancelled() }}
uses: pmeier/pytest-results-action@v0.8.0
uses: actions/upload-artifact@v4
with:
name: test-results
path: tests/.tests.xml
title: Test results
summary: true
display-options: fEX
fail-on-empty: false

- name: Setup docs cache
timeout-minutes: 10
if: ${{ !cancelled() }}
uses: actions/cache@v5
with:
path: docs/build
key: docs-cache-${{ hashFiles('docs') }}

- name: Build docs
timeout-minutes: 10
if: ${{ !cancelled() }}
run: pdm run docs

- name: Setup Github Pages
- name: Upload docs artifact
timeout-minutes: 10
if: ${{ !cancelled() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
uses: actions/upload-artifact@v4
with:
name: docs-build
path: "./docs/build"

# ──────────────────────────────────────────────────────────────────
# Deploy docs — only on push to main
# ──────────────────────────────────────────────────────────────────
deploy-docs:
name: deploy docs
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: ci
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
pages: write
id-token: write
steps:
- name: Download docs artifact
timeout-minutes: 10
uses: actions/download-artifact@v4
with:
name: docs-build
path: "./docs/build"

- name: Setup Github Pages
timeout-minutes: 10
uses: actions/configure-pages@v5

- name: Upload docs to Github Pages
timeout-minutes: 10
if: ${{ !cancelled() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
uses: actions/upload-pages-artifact@v4
with:
path: './docs/build'
path: "./docs/build"

- name: Deploy GitHub Pages
timeout-minutes: 10
if: ${{ !cancelled() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
uses: actions/deploy-pages@v4
Loading