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
4 changes: 0 additions & 4 deletions .github/ISSUE_TEMPLATE/cron_comment_template.md

This file was deleted.

3 changes: 0 additions & 3 deletions .github/ISSUE_TEMPLATE/cron_comment_template.md.license

This file was deleted.

88 changes: 88 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# SPDX-FileCopyrightText: 2006-2026 Knut Reinert & Freie Universität Berlin
# SPDX-FileCopyrightText: 2016-2026 Knut Reinert & MPI für molekulare Genetik
# SPDX-License-Identifier: CC0-1.0

# Staged CI: cheap checks -> Linux unit tests -> everything else. A later stage only starts if the earlier ones passed,
# so a formatting error costs one short Lint job instead of a full CI run.
#
# Stage 1 Lint (ci_lint.yml), License (ci_license.yml)
# Stage 2 Unit Linux (ci_linux.yml)
# Stage 3 CMake, Coverage, Unit macOS, Linux
#
# Runs PR code, therefore only `pull_request`: read-only GITHUB_TOKEN, no secrets for fork PRs. If Lint fails,
# lint_autofix.yml (from the default branch) pushes the formatting fix, which starts CI again.
# The only required status check is "CI result" (plus "Documentation", which stays a separate workflow).

name: CI

on:
push:
branches:
- 'main'
pull_request:
workflow_dispatch:

# Replaces the cancel_running_workflows job of the old lint workflow: a new push to a PR cancels all stages.
concurrency:
group: ci-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name != 'push' }}

permissions:
contents: read

jobs:
# Stage 1. As in all of the repository's workflows: on forks, only when started by hand.
lint:
name: Lint
if: github.repository_owner == 'seqan' || github.event_name == 'workflow_dispatch'
uses: ./.github/workflows/ci_lint.yml
license:
name: License
if: github.repository_owner == 'seqan' || github.event_name == 'workflow_dispatch'
uses: ./.github/workflows/ci_license.yml

# Stage 2
linux:
name: Unit Linux
needs: [lint, license]
uses: ./.github/workflows/ci_linux.yml

# Stage 3. Coverage gets the Codecov token; the other stages need no secrets.
cmake:
name: CMake
needs: linux
uses: ./.github/workflows/ci_cmake.yml
coverage:
name: Coverage
needs: linux
uses: ./.github/workflows/ci_coverage.yml
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
macos:
name: Unit macOS
needs: linux
uses: ./.github/workflows/ci_macos.yml
misc:
name: Linux
needs: linux
uses: ./.github/workflows/ci_misc.yml

# The single required check. Required checks cannot simply list the stages: a skipped job reports "Success", and a
# skipped matrix job reports under its unexpanded name. This gate runs always and fails unless every stage
# succeeded (skipped and cancelled count as failure).
result:
name: CI result
if: always() && (github.repository_owner == 'seqan' || github.event_name == 'workflow_dispatch')
needs: [lint, license, linux, cmake, coverage, macos, misc]
runs-on: ubuntu-latest
steps:
- name: Check stage results
env:
RESULTS: ${{ join(needs.*.result, ' ') }}
run: |
for result in ${RESULTS}; do
if [[ ${result} != success ]]; then
echo "::error::Not every CI stage succeeded: ${RESULTS}"
exit 1
fi
done
13 changes: 2 additions & 11 deletions .github/workflows/ci_cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,9 @@
name: CMake

on:
push:
branches:
- 'main'
pull_request:
types:
- unlabeled
workflow_call:
workflow_dispatch:

concurrency:
group: cmake-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name != 'push' }}

env:
SEQAN3_NO_VERSION_CHECK: 1
TZ: Europe/Berlin
Expand All @@ -29,7 +20,7 @@ jobs:
build:
name: ${{ matrix.name }}
runs-on: ubuntu-latest
if: github.repository_owner == 'seqan' || github.event_name == 'workflow_dispatch' || github.event.label.name == 'lint'
if: github.repository_owner == 'seqan' || github.event_name == 'workflow_dispatch'
strategy:
fail-fast: false
matrix:
Expand Down
16 changes: 5 additions & 11 deletions .github/workflows/ci_coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,12 @@
name: Coverage

on:
push:
branches:
- 'main'
pull_request:
types:
- unlabeled
workflow_call:
secrets:
CODECOV_TOKEN:
required: false
workflow_dispatch:

concurrency:
group: coverage-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: false

env:
SEQAN3_NO_VERSION_CHECK: 1
TZ: Europe/Berlin
Expand All @@ -29,7 +23,7 @@ jobs:
build:
runs-on: ubuntu-latest
name: ${{ matrix.compiler }}
if: github.repository_owner == 'seqan' || github.event_name == 'workflow_dispatch' || github.event.label.name == 'lint'
if: github.repository_owner == 'seqan' || github.event_name == 'workflow_dispatch'
strategy:
fail-fast: false
matrix:
Expand Down
90 changes: 50 additions & 40 deletions .github/workflows/ci_documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,26 @@
# SPDX-FileCopyrightText: 2016-2026 Knut Reinert & MPI für molekulare Genetik
# SPDX-License-Identifier: CC0-1.0

# Builds and tests the documentation. PRs: upload the HTML; docs_preview.yml publishes it from the default branch.
# Push to main: deploy to docs.seqan.de from a separate job, so the server key never shares a job with
# CMake/Doxygen. Stays a separate workflow (not a CI stage) so that the preview appears as soon as this finishes.

name: Documentation

on:
push:
branches:
- 'main'
pull_request_target:
types:
- unlabeled
- closed
pull_request:
workflow_dispatch:

concurrency:
group: documentation-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name != 'push' }}

permissions:
contents: read

env:
SEQAN3_NO_VERSION_CHECK: 1
TZ: Europe/Berlin
Expand All @@ -30,19 +34,12 @@ jobs:
build:
name: Documentation
runs-on: ubuntu-latest
if: ( github.repository_owner == 'seqan' || github.event_name == 'workflow_dispatch' || github.event.label.name == 'lint' ) && github.event.action != 'closed'
if: github.repository_owner == 'seqan' || github.event_name == 'workflow_dispatch'
steps:
- name: Checkout
if: github.event_name != 'pull_request_target'
uses: actions/checkout@v7

# pull_request_target does not checkout the merge commit by default
- name: Checkout
if: github.event_name == 'pull_request_target'
uses: actions/checkout@v7
uses: actions/checkout@v7 # locked via actions.lock
with:
ref: "refs/pull/${{ github.event.number }}/merge"
allow-unsafe-pr-checkout: true
persist-credentials: false

- name: Install Doxygen
uses: seqan/actions/setup-doxygen@main
Expand All @@ -58,38 +55,51 @@ jobs:
working-directory: build
run: ctest . -j --output-on-failure --no-tests=error

- name: Deploy Preview
if: github.event_name == 'pull_request_target'
uses: seqan/actions/documentation_deploy_preview@main
# For docs_preview.yml (PRs) and the deploy job below. docs_preview.yml expects these artifact names.
- name: Upload documentation
uses: actions/upload-artifact@v7 # locked via actions.lock
with:
deploy_host: ${{ secrets.DEPLOY_HOST }}
deploy_user: ${{ secrets.DEPLOY_USER }}
deploy_ssh_key: ${{ secrets.DEPLOY_SSH_KEY }}
deploy_base_path: ${{ secrets.DEPLOY_PREVIEW_BASE_PATH }}
source_path_user_doc: build/doc_usr/html
source_path_developer_doc: build/doc_dev/html
token: ${{ secrets.SEQAN_ACTIONS_PAT }}
name: documentation
path: build/doc_usr/html/
retention-days: 7
if-no-files-found: error

- name: Deploy Documentation
if: github.event_name == 'push'
- name: Upload developer documentation
uses: actions/upload-artifact@v7 # locked via actions.lock
with:
name: documentation-developer
path: build/doc_dev/html/
retention-days: 7
if-no-files-found: error

deploy:
name: Deploy Documentation
needs: build
if: github.repository_owner == 'seqan' && github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: server-deploy # deployment branches: main; holds the server key
steps:
- name: Download documentation
uses: actions/download-artifact@v8 # locked via actions.lock
with:
name: documentation
path: html_user

- name: Download developer documentation
uses: actions/download-artifact@v8 # locked via actions.lock
with:
name: documentation-developer
path: html_dev

# Plain rsync with a pinned host key (no third-party deploy action): the key grants the whole server.
# Same targets as before.
- name: Deploy
uses: seqan/actions/documentation_deploy_production@main
with:
deploy_host: ${{ secrets.DEPLOY_HOST }}
deploy_user: ${{ secrets.DEPLOY_USER }}
deploy_ssh_key: ${{ secrets.DEPLOY_SSH_KEY }}
source_path_user_doc: build/doc_usr/html/
source_path_user_doc: html_user/
deploy_path_user_doc: ${{ secrets.DEPLOY_PRODUCTION_BASE_PATH }}/main_user
source_path_developer_doc: build/doc_dev/html/
source_path_developer_doc: html_dev/
deploy_path_developer_doc: ${{ secrets.DEPLOY_PRODUCTION_BASE_PATH }}/main_dev
delete:
name: Delete Preview
runs-on: ubuntu-latest
if: github.repository_owner == 'seqan' && github.event_name == 'pull_request_target' && github.event.action == 'closed'
steps:
- name: Delete Preview
uses: seqan/actions/documentation_delete_preview@main
with:
deploy_host: ${{ secrets.DEPLOY_HOST }}
deploy_user: ${{ secrets.DEPLOY_USER }}
deploy_ssh_key: ${{ secrets.DEPLOY_SSH_KEY }}
deploy_base_path: ${{ secrets.DEPLOY_PREVIEW_BASE_PATH }}
13 changes: 2 additions & 11 deletions .github/workflows/ci_license.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,9 @@
name: License

on:
push:
branches:
- 'main'
pull_request:
types:
- unlabeled
workflow_call:
workflow_dispatch:

concurrency:
group: license-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name != 'push' }}

env:
TZ: Europe/Berlin

Expand All @@ -29,7 +20,7 @@ jobs:
name: REUSE Compliance
runs-on: ubuntu-latest
timeout-minutes: 120
if: github.repository_owner == 'seqan' || github.event_name == 'workflow_dispatch' || github.event.label.name == 'lint'
if: github.repository_owner == 'seqan' || github.event_name == 'workflow_dispatch'
steps:
- name: Checkout
uses: actions/checkout@v7
Expand Down
50 changes: 24 additions & 26 deletions .github/workflows/ci_lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,44 @@
# SPDX-FileCopyrightText: 2016-2026 Knut Reinert & MPI für molekulare Genetik
# SPDX-License-Identifier: CC0-1.0

# Stage 1 of ci.yml. Check only: formats the checkout with seqan/actions/lint and fails if that changed anything.
# The CI run then ends early (later stages are skipped), and lint_autofix.yml pushes the formatting commit, which
# starts a new CI run. The diff is shown in the job summary, for PRs the bot cannot push to.

name: Lint

on:
pull_request_target:
workflow_call:

env:
TZ: Europe/Berlin
permissions:
contents: read

defaults:
run:
shell: bash -Eeuxo pipefail {0}

jobs:
# Cancel other workflows that are dependent on this workflow by adding jobs that have the same concurrency group.
cancel_running_workflows:
name: Cancel ${{ matrix.workflow}}
strategy:
fail-fast: false
matrix:
workflow: ["linux", "macos", "misc", "coverage", "cmake", "documentation"]
concurrency:
group: ${{ matrix.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
runs-on: ubuntu-latest
steps:
- name: "Cancel ${{ matrix.workflow }}"
run: echo "Cancelling ${{ matrix.workflow }}"
lint:
name: Lint
concurrency:
group: lint-${{ github.event.pull_request.number }}
cancel-in-progress: true
needs: cancel_running_workflows
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Run lint
- name: Checkout
uses: actions/checkout@v7 # locked via actions.lock
with:
fetch-depth: 0
persist-credentials: false

# Files changed since: the PR's base (pull_request), the previous tip (push), or the last commit (dispatch).
- name: Format
uses: seqan/actions/lint@main
with:
clang_format: 18
token: ${{ secrets.SEQAN_ACTIONS_PAT }}
gpg_key: ${{ secrets.SEQAN_ACTIONS_GPG_KEY }}
gpg_passphrase: ${{ secrets.SEQAN_ACTIONS_GPG_PASSPHRASE }}
base: ${{ github.event.pull_request.base.sha || github.event.before || 'HEAD~1' }}

- name: Check
run: |
if ! git diff --quiet; then
{ echo '### Formatting required'; echo '```diff'; git diff; echo '```'; } >> "${GITHUB_STEP_SUMMARY}"
echo "::error::Formatting required. The bot pushes a fix if the PR allows edits by maintainers."
exit 1
fi
Loading
Loading