Skip to content
Open
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
7 changes: 7 additions & 0 deletions .github/workflows/mac.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ name: macOS

on:
workflow_call:
inputs:
ppc_tasks:
description: 'Tasks to build'
required: false
type: string
default: all

permissions:
contents: read
Expand Down Expand Up @@ -37,6 +43,7 @@ jobs:
-DCMAKE_C_FLAGS="-I$(brew --prefix)/opt/libomp/include"
-DCMAKE_CXX_FLAGS="-I$(brew --prefix)/opt/libomp/include"
-D CMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_INSTALL_PREFIX=install
-D PPC_TASKS="${{ inputs.ppc_tasks }}"
- name: Build project
run: |
cmake --build build --parallel -- --quiet
Expand Down
36 changes: 36 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,58 @@ concurrency:
!startsWith(github.ref, 'refs/heads/gh-readonly-queue') }}

jobs:
ci-scope:
runs-on: ubuntu-24.04
outputs:
ppc_tasks: ${{ steps.detect.outputs.ppc_tasks }}
task_scoped: ${{ steps.detect.outputs.task_scoped }}
steps:
- uses: actions/checkout@v6
if: ${{ github.event_name == 'pull_request' }}
with:
fetch-depth: 0
- name: Detect CI task scope
id: detect
env:
EVENT_NAME: ${{ github.event_name }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
if [ "$EVENT_NAME" != "pull_request" ]; then
echo "ppc_tasks=all" >> "$GITHUB_OUTPUT"
echo "task_scoped=false" >> "$GITHUB_OUTPUT"
echo "PPC_TASKS=all"
exit 0
fi

python3 scripts/detect_ci_task_scope.py \
--base-sha "$BASE_SHA" \
--head-sha "$HEAD_SHA" \
--github-output "$GITHUB_OUTPUT"
pre-commit:
uses: ./.github/workflows/pre-commit.yml
ubuntu:
needs:
- ci-scope
- pre-commit
uses: ./.github/workflows/ubuntu.yml
with:
is_nightly: ${{ github.event_name == 'schedule' }}
ppc_tasks: ${{ needs.ci-scope.outputs.ppc_tasks || 'all' }}
mac:
needs:
- ci-scope
- pre-commit
uses: ./.github/workflows/mac.yml
with:
ppc_tasks: ${{ needs.ci-scope.outputs.ppc_tasks || 'all' }}
windows:
needs:
- ci-scope
- pre-commit
uses: ./.github/workflows/windows.yml
with:
ppc_tasks: ${{ needs.ci-scope.outputs.ppc_tasks || 'all' }}
perf:
needs:
- ubuntu
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/static-analysis-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,28 @@ permissions:
packages: read

jobs:
ci-scope:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static-analysis-pr.yml now depends on scripts/detect_ci_task_scope.py to decide the PPC_TASKS value used by the clang-tidy jobs, but that script is not listed in on.pull_request.paths. A PR that changes only this detector would skip the Static analysis workflow entirely, so regressions in CI scoping would not be validated. Please add scripts/detect_ci_task_scope.py to the workflow path filters.

runs-on: ubuntu-24.04
outputs:
ppc_tasks: ${{ steps.detect.outputs.ppc_tasks }}
task_scoped: ${{ steps.detect.outputs.task_scoped }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Detect CI task scope
id: detect
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
python3 scripts/detect_ci_task_scope.py \
--base-sha "$BASE_SHA" \
--head-sha "$HEAD_SHA" \
--github-output "$GITHUB_OUTPUT"
clang-tidy:
needs:
- ci-scope
runs-on: ubuntu-24.04
container:
image: ghcr.io/learning-process/ppc-ubuntu:1.2
Expand All @@ -48,6 +69,7 @@ jobs:
run: >
cmake -S . -B build -G Ninja
-D CMAKE_BUILD_TYPE=RELEASE -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_COMPILE_WARNING_AS_ERROR=ON
-D PPC_TASKS="${{ needs.ci-scope.outputs.ppc_tasks || 'all' }}"
env:
CC: clang-22
CXX: clang++-22
Expand All @@ -73,6 +95,7 @@ jobs:
exit 1
clang-tidy-for-gcc-build:
needs:
- ci-scope
- clang-tidy
runs-on: ubuntu-24.04
container:
Expand All @@ -97,6 +120,7 @@ jobs:
run: >
cmake -S . -B build -G Ninja
-D CMAKE_BUILD_TYPE=RELEASE -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_COMPILE_WARNING_AS_ERROR=ON
-D PPC_TASKS="${{ needs.ci-scope.outputs.ppc_tasks || 'all' }}"
env:
CC: gcc-14
CXX: g++-14
Expand Down
9 changes: 9 additions & 0 deletions .github/workflows/ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ on:
required: false
type: boolean
default: false
ppc_tasks:
description: 'Tasks to build'
required: false
type: string
default: all

permissions:
contents: read
Expand Down Expand Up @@ -39,6 +44,7 @@ jobs:
run: >
cmake -S . -B build -G Ninja
-D CMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_INSTALL_PREFIX=install
-D PPC_TASKS="${{ inputs.ppc_tasks }}"
env:
CC: gcc-14
CXX: g++-14
Expand Down Expand Up @@ -148,6 +154,7 @@ jobs:
run: >
cmake -S . -B build -G Ninja
-D CMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=install
-D PPC_TASKS="${{ inputs.ppc_tasks }}"
env:
CC: clang-22
CXX: clang++-22
Expand Down Expand Up @@ -253,6 +260,7 @@ jobs:
-D CMAKE_BUILD_TYPE=RelWithDebInfo
-D ENABLE_ADDRESS_SANITIZER=ON -D ENABLE_UB_SANITIZER=ON -D ENABLE_LEAK_SANITIZER=ON
-D CMAKE_INSTALL_PREFIX=install
-D PPC_TASKS="${{ inputs.ppc_tasks }}"
env:
CC: clang-22
CXX: clang++-22
Expand Down Expand Up @@ -368,6 +376,7 @@ jobs:
-D CMAKE_BUILD_TYPE=RELEASE
-D CMAKE_VERBOSE_MAKEFILE=ON -D USE_COVERAGE=ON
-DCMAKE_INSTALL_PREFIX=install
-D PPC_TASKS="${{ inputs.ppc_tasks }}"
- name: Build project
run: |
cmake --build build --parallel -- --quiet
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ name: Windows

on:
workflow_call:
inputs:
ppc_tasks:
description: 'Tasks to build'
required: false
type: string
default: all

permissions:
contents: read
Expand All @@ -26,6 +32,7 @@ jobs:
cmake -S . -B build -G Ninja -D CMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl
-D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache
-D CMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_INSTALL_PREFIX=install
-D PPC_TASKS="${{ inputs.ppc_tasks }}"
- name: Build project
shell: bash
run: |
Expand Down Expand Up @@ -108,6 +115,7 @@ jobs:
-D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache
-D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=install
-D CMAKE_PREFIX_PATH="C:/Program Files/LLVM"
-D PPC_TASKS="${{ inputs.ppc_tasks }}"
env:
CC: clang-cl
CXX: clang-cl
Expand Down
86 changes: 86 additions & 0 deletions scripts/detect_ci_task_scope.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/usr/bin/env python3

import argparse
import subprocess
from pathlib import Path, PurePosixPath

FULL_SUITE = "all"


def _changed_files(base_sha: str, head_sha: str) -> list[str]:
result = subprocess.run(
["git", "diff", "--name-only", "--no-renames", f"{base_sha}...{head_sha}"],
check=True,
stdout=subprocess.PIPE,
text=True,
)
return [line for line in result.stdout.splitlines() if line]


def _task_from_path(path: str, tasks_root: Path) -> str | None:
parts = PurePosixPath(path).parts
if len(parts) < 3 or parts[0] != "tasks" or parts[1] == "common":
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid scoping .clang-tidy changes to one task

When a PR changes a task-local config such as tasks/example_threads/tests/.clang-tidy, this accepts it as task-scoped and the static-analysis workflow configures CMake with only that task. However the existing clang-tidy action treats any .clang-tidy change as a request to analyze all source files (.github/actions/clang-tidy-native/action.yml lines 35-43), so files from other tasks will not have entries in the scoped compile_commands.json and clang-tidy can fail or run with incorrect fallback flags. Please force the full suite for .clang-tidy changes, or make the analysis file list use the same task scope.

Useful? React with 👍 / 👎.

return None

task_id = parts[1]
if not (tasks_root / task_id).is_dir():
return None

return task_id


def detect_scope(changed_files: list[str], tasks_root: Path) -> tuple[str, bool]:
task_ids = set()

for changed_file in changed_files:
task_id = _task_from_path(changed_file, tasks_root)
if task_id is None:
return FULL_SUITE, False
task_ids.add(task_id)

if not task_ids:
return FULL_SUITE, False

return ";".join(sorted(task_ids)), True


def _write_github_output(github_output: Path, scope: str, task_scoped: bool) -> None:
with github_output.open("a", encoding="utf-8") as output:
output.write(f"ppc_tasks={scope}\n")
output.write(f"task_scoped={str(task_scoped).lower()}\n")


def _parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(
description="Detect the PPC_TASKS value for CI from changed PR paths.",
)
parser.add_argument(
"--base-sha", required=True, help="Base commit for the PR diff."
)
parser.add_argument(
"--head-sha", required=True, help="Head commit for the PR diff."
)
parser.add_argument(
"--tasks-root", default="tasks", type=Path, help="Path to the tasks directory."
)
parser.add_argument(
"--github-output",
type=Path,
help="Optional GITHUB_OUTPUT file to append workflow outputs.",
)
return parser.parse_args()


def main() -> None:
args = _parse_args()
scope, task_scoped = detect_scope(
_changed_files(args.base_sha, args.head_sha), args.tasks_root
)

print(f"PPC_TASKS={scope}")
if args.github_output is not None:
_write_github_output(args.github_output, scope, task_scoped)


if __name__ == "__main__":
main()
Loading