From a6578fa94147e0461a00b1c8a79f1c7b03341ed0 Mon Sep 17 00:00:00 2001 From: Alexander Lanin Date: Tue, 31 Mar 2026 23:48:48 +0200 Subject: [PATCH 1/4] feat: new on-pr workflow for all the basics --- .github/workflows/on-pr.yml | 188 +++++++++++++++++++++++++++- scripts/detect-bazel-targets.sh | 62 +++++++++ scripts/detect-repo-capabilities.sh | 71 +++++++++++ 3 files changed, 315 insertions(+), 6 deletions(-) create mode 100755 scripts/detect-bazel-targets.sh create mode 100755 scripts/detect-repo-capabilities.sh diff --git a/.github/workflows/on-pr.yml b/.github/workflows/on-pr.yml index 91baffa..fe2b042 100644 --- a/.github/workflows/on-pr.yml +++ b/.github/workflows/on-pr.yml @@ -1,5 +1,5 @@ # ******************************************************************************* -# Copyright (c) 2025 Contributors to the Eclipse Foundation +# Copyright (c) 2026 Contributors to the Eclipse Foundation # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. @@ -11,12 +11,188 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -name: on-pr +# This is designed as the main entry point for PR checks, for all S-CORE repositories. + +# Attention: this workflow must be called with following permissions: +# permissions: +# id-token: write + +# The name will show up as "PR Checl / ๐Ÿ” / ", +# so there is no reason to add any text where the icon is. +name: ๐Ÿ” on: - pull_request: - branches: [main] + workflow_call: jobs: - score-pr-checks: - uses: ./.github/workflows/score-pr-checks.yml + detect-repo-capabilities: + name: Detect repository capabilities + runs-on: ${{ vars.REPO_RUNNER_LABELS && fromJSON(vars.REPO_RUNNER_LABELS) || 'ubuntu-24.04' }} + outputs: + has_bazel: ${{ steps.detect.outputs.has_bazel }} + has_bazel_lock: ${{ steps.detect.outputs.has_bazel_lock }} + has_devcontainer: ${{ steps.detect.outputs.has_devcontainer }} + has_python_uv: ${{ steps.detect.outputs.has_python_uv }} + has_precommit: ${{ steps.detect.outputs.has_precommit }} + + permissions: + id-token: write + contents: read + + steps: + - name: ๐Ÿ“ฅ Check out + uses: actions/checkout@v6 + + - name: ๐Ÿ“ฅ Check out cicd-workflows + uses: dariocurr/checkout-called@v6 + with: + path: .cicd-workflows + + - name: ๐Ÿ•ต๏ธ Detect repository capabilities + id: detect + run: ./.cicd-workflows/scripts/detect-repo-capabilities.sh "${{ github.workspace }}" + + precommit: + name: ๐Ÿงน Run pre-commit checks + needs: detect-repo-capabilities + if: needs.detect-repo-capabilities.outputs.has_precommit == 'true' + runs-on: ${{ vars.REPO_RUNNER_LABELS && fromJSON(vars.REPO_RUNNER_LABELS) || 'ubuntu-24.04' }} + steps: + - name: ๐Ÿ“ฅ Check out + uses: actions/checkout@v6 + - name: โš™๏ธ Setup uv + uses: astral-sh/setup-uv@v5 + - name: ๐Ÿ› ๏ธ Run pre-commit + run: uvx pre-commit run --all-files + + python-uv-pytest: + name: ๐Ÿ Run Python tests with uv + needs: detect-repo-capabilities + if: needs.detect-repo-capabilities.outputs.has_python_uv == 'true' + runs-on: ${{ vars.REPO_RUNNER_LABELS && fromJSON(vars.REPO_RUNNER_LABELS) || 'ubuntu-24.04' }} + steps: + - name: ๐Ÿ“ฅ Check out + uses: actions/checkout@v6 + + - name: โš™๏ธ Setup uv + uses: astral-sh/setup-uv@v5 + + - name: Run checks via uv + run: uv run --frozen python -m pytest + + bazel-bzlmod-lock-check: + name: ๐Ÿ”’ Check Bazel Bzlmod lockfile + needs: detect-repo-capabilities + if: needs.detect-repo-capabilities.outputs.has_bazel_lock == 'true' + uses: ./.github/workflows/bzlmod-lock-check.yml + + bazel-module-name-check: + name: ๐Ÿ“ Check Bazel module name + needs: detect-repo-capabilities + if: needs.detect-repo-capabilities.outputs.has_bazel == 'true' + runs-on: ${{ vars.REPO_RUNNER_LABELS && fromJSON(vars.REPO_RUNNER_LABELS) || 'ubuntu-24.04' }} + steps: + - name: ๐Ÿ“ฅ Check out + uses: actions/checkout@v6 + + - name: ๐Ÿ“ Validate Bazel module name + run: | + if ! MODULE_LINE=$(grep '^module(' MODULE.bazel | head -1); then + echo "โŒ No module declaration found in MODULE.bazel" + exit 1 + fi + + MODULE_NAME=$(echo "$MODULE_LINE" | sed 's/^module([[:space:]]*name[[:space:]]*=[[:space:]]*"\([^"]*\)".*/\1/' | sed 's/^module([[:space:]]*"\([^"]*\)".*/\1/') + + if [[ -z "$MODULE_NAME" || "$MODULE_NAME" == "$MODULE_LINE" ]]; then + MODULE_NAME=$(echo "$MODULE_LINE" | grep -o '"[^"]*"' | head -1 | tr -d '"') + fi + + echo "Found module name: $MODULE_NAME" + + if [[ ! "$MODULE_NAME" =~ ^score_[[:lower:]_]+$ ]]; then + echo "โŒ Invalid module name: $MODULE_NAME" + echo "Module name must match the pattern: ^score_[[:lower:]_]+$" + echo " - Must start with 'score_'" + echo " - Must contain only lowercase letters and underscores after 'score_'" + echo "Examples of valid names: score_cli, score_compose, score_web_api" + exit 1 + fi + + echo "โœ… Module name is valid: $MODULE_NAME" + + detect-repo-bazel-targets: + name: Detect repo bazel targets + needs: detect-repo-capabilities + if: needs.detect-repo-capabilities.outputs.has_bazel == 'true' + runs-on: ${{ vars.REPO_RUNNER_LABELS && fromJSON(vars.REPO_RUNNER_LABELS) || 'ubuntu-24.04' }} + outputs: + has_copyright_check: ${{ steps.detect.outputs.has_copyright_check }} + has_format_check: ${{ steps.detect.outputs.has_format_check }} + + permissions: + id-token: write + contents: read + + steps: + - name: ๐Ÿ“ฅ Check out + uses: actions/checkout@v6 + + - name: ๐Ÿ“ฅ Check out cicd-workflows + uses: dariocurr/checkout-called@v6 + with: + path: .cicd-workflows + + - name: โš™๏ธ Setup Bazel with shared caching + uses: bazel-contrib/setup-bazel@0.18.0 + with: + disk-cache: false + repository-cache: false + bazelisk-cache: true + cache-save: false + + - name: ๐Ÿ•ต๏ธ Detect Bazel targets + id: detect + run: ./.cicd-workflows/scripts/detect-bazel-targets.sh "${{ github.workspace }}" + + bazel-format-check: + name: ๐Ÿ–Œ๏ธ Run bazel //:format.check + needs: detect-repo-bazel-targets + if: needs.detect-repo-bazel-targets.outputs.has_format_check == 'true' + runs-on: ${{ vars.REPO_RUNNER_LABELS && fromJSON(vars.REPO_RUNNER_LABELS) || 'ubuntu-24.04' }} + steps: + - name: ๐Ÿ“ฅ Check out + uses: actions/checkout@v6 + + - name: โš™๏ธ Setup Bazel with shared caching + uses: bazel-contrib/setup-bazel@0.18.0 + with: + disk-cache: false + repository-cache: false + bazelisk-cache: true + cache-save: false + + - name: ๐Ÿ–Œ๏ธ Run formatting check + run: bazel test //:format.check + + bazel-copyright-check: + name: ยฉ Run bazel //:copyright.check + needs: + - detect-repo-capabilities + - detect-repo-bazel-targets + if: needs.detect-repo-capabilities.outputs.has_bazel == 'true' && needs.detect-repo-bazel-targets.outputs.has_copyright_check == 'true' + runs-on: ${{ vars.REPO_RUNNER_LABELS && fromJSON(vars.REPO_RUNNER_LABELS) || 'ubuntu-24.04' }} + steps: + - name: ๐Ÿ“ฅ Check out + uses: actions/checkout@v6 + + - name: โš™๏ธ Setup Bazel with shared caching + uses: bazel-contrib/setup-bazel@0.18.0 + with: + disk-cache: false + repository-cache: false + bazelisk-cache: true + cache-save: false + + - name: ยฉ Run copyright check + run: bazel test //:copyright.check diff --git a/scripts/detect-bazel-targets.sh b/scripts/detect-bazel-targets.sh new file mode 100755 index 0000000..e2edef4 --- /dev/null +++ b/scripts/detect-bazel-targets.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash + +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +set -euo pipefail + +repo="${1:?Repository path is required}" + +if ! [[ -f "$repo/MODULE.bazel" || -f "$repo/WORKSPACE" || -f "$repo/WORKSPACE.bazel" ]]; then + echo "ERROR: Not a Bazel workspace; you cannot run this script here." >&2 + exit 1 +fi + +if ! command -v bazel >/dev/null 2>&1; then + echo "ERROR: bazel is not available on PATH; you need that to run this script." >&2 + exit 1 +fi + +if [[ -z "${GITHUB_OUTPUT:-}" ]]; then + echo "WARNING: This action is designed to be used in a GitHub Actions workflow. Running in 'local mode'." >&2 + GITHUB_OUTPUT=/dev/stdout +fi + +echo "::group:: Detecting Bazel targets" + +# Runs a boolean-style check function and writes to GITHUB_OUTPUT. +emit_output() { + local name="$1" + shift + + if "$@"; then + echo "$name=true" >> "$GITHUB_OUTPUT" + else + echo "$name=false" >> "$GITHUB_OUTPUT" + fi +} + +# Returns success if the given Bazel label can be queried from the repo root. +has_bazel_target() { + local target="$1" + + ( + cd "$repo" + bazel query "$target" >/dev/null 2>&1 + ) +} + +emit_output has_copyright_check has_bazel_target "//:copyright.check" +emit_output has_format_check has_bazel_target "//:format.check" + +echo "::endgroup::" diff --git a/scripts/detect-repo-capabilities.sh b/scripts/detect-repo-capabilities.sh new file mode 100755 index 0000000..ce3fe5b --- /dev/null +++ b/scripts/detect-repo-capabilities.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash + +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +set -euo pipefail + +repo="${1:?Repository path is required}" +if [[ -z "${GITHUB_OUTPUT:-}" ]]; then + echo "WARNING: This action is designed to be used in a GitHub Actions workflow. Running in 'local mode'." >&2 + GITHUB_OUTPUT=/dev/stdout +fi + +echo "::group:: Detecting repository capabilities" + +# Runs a boolean-style check function and writes to GITHUB_OUTPUT. +emit_output() { + local name="$1" + shift + + if "$@"; then + echo "$name=true" >> "$GITHUB_OUTPUT" + else + echo "$name=false" >> "$GITHUB_OUTPUT" + fi +} + +# Returns success if any provided file path exists. +any_file_exists() { + local path + for path in "$@"; do + [[ -f "$path" ]] && return 0 + done + return 1 +} + +# Returns success only if every provided file path exists. +all_files_exist() { + local path + for path in "$@"; do + [[ -f "$path" ]] || return 1 + done + return 0 +} + +emit_output has_bazel any_file_exists \ + "$repo/MODULE.bazel" \ + "$repo/WORKSPACE" \ + "$repo/WORKSPACE.bazel" +emit_output has_bazel_lock any_file_exists \ + "$repo/MODULE.bazel.lock" +emit_output has_devcontainer any_file_exists \ + "$repo/.devcontainer/devcontainer.json" \ + "$repo/devcontainer.json" +emit_output has_python_uv all_files_exist \ + "$repo/pyproject.toml" \ + "$repo/uv.lock" +emit_output has_precommit any_file_exists \ + "$repo/.pre-commit-config.yaml" + +echo "::endgroup::" From 2b6b157381f1726c6b2c29f50b1e5758e6bd2171 Mon Sep 17 00:00:00 2001 From: Alexander Lanin Date: Wed, 1 Apr 2026 00:26:47 +0200 Subject: [PATCH 2/4] fixes --- .github/workflows/on-pr.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/on-pr.yml b/.github/workflows/on-pr.yml index fe2b042..659bad1 100644 --- a/.github/workflows/on-pr.yml +++ b/.github/workflows/on-pr.yml @@ -19,6 +19,8 @@ # The name will show up as "PR Checl / ๐Ÿ” / ", # so there is no reason to add any text where the icon is. +# --- +# Update: this name is actually not used anywhere! wtf? name: ๐Ÿ” on: @@ -89,7 +91,8 @@ jobs: bazel-module-name-check: name: ๐Ÿ“ Check Bazel module name needs: detect-repo-capabilities - if: needs.detect-repo-capabilities.outputs.has_bazel == 'true' + # The script to detect the module name is broken + if: needs.detect-repo-capabilities.outputs.has_bazel == 'true' && false runs-on: ${{ vars.REPO_RUNNER_LABELS && fromJSON(vars.REPO_RUNNER_LABELS) || 'ubuntu-24.04' }} steps: - name: ๐Ÿ“ฅ Check out @@ -195,4 +198,4 @@ jobs: cache-save: false - name: ยฉ Run copyright check - run: bazel test //:copyright.check + run: bazel run //:copyright.check From 941e3e9d09407efa1ec94e122be53e068f515263 Mon Sep 17 00:00:00 2001 From: Alexander Lanin Date: Wed, 1 Apr 2026 00:32:24 +0200 Subject: [PATCH 3/4] run on-pr locally --- .github/workflows/_local_on_pr.yml | 21 +++++++-------------- .github/workflows/on-pr.yml | 6 ++---- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/.github/workflows/_local_on_pr.yml b/.github/workflows/_local_on_pr.yml index cd8714d..e3da3c5 100644 --- a/.github/workflows/_local_on_pr.yml +++ b/.github/workflows/_local_on_pr.yml @@ -11,22 +11,15 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -name: Pull Request Workflow +name: PR on: pull_request: types: [opened, reopened, synchronize] + merge_group: + types: [checks_requested] jobs: - - self_test: - name: ๐Ÿ”ฌ Self Test - runs-on: ubuntu-latest - steps: - - name: ๐Ÿ“ฅ Check out - uses: actions/checkout@v6 - - - name: โš™๏ธ Setup uv - uses: astral-sh/setup-uv@v5 - - - name: ๐Ÿ› ๏ธ Run pre-commit - run: uvx pre-commit run --all-files + common: + uses: ./.github/workflows/on-pr.yml + permissions: + id-token: write diff --git a/.github/workflows/on-pr.yml b/.github/workflows/on-pr.yml index 659bad1..7976f4c 100644 --- a/.github/workflows/on-pr.yml +++ b/.github/workflows/on-pr.yml @@ -180,10 +180,8 @@ jobs: bazel-copyright-check: name: ยฉ Run bazel //:copyright.check - needs: - - detect-repo-capabilities - - detect-repo-bazel-targets - if: needs.detect-repo-capabilities.outputs.has_bazel == 'true' && needs.detect-repo-bazel-targets.outputs.has_copyright_check == 'true' + needs: detect-repo-bazel-targets + if: needs.detect-repo-bazel-targets.outputs.has_copyright_check == 'true' runs-on: ${{ vars.REPO_RUNNER_LABELS && fromJSON(vars.REPO_RUNNER_LABELS) || 'ubuntu-24.04' }} steps: - name: ๐Ÿ“ฅ Check out From 53402503cdaf7bcdb88c26e647d54d6d3f6dfbe2 Mon Sep 17 00:00:00 2001 From: Alexander Lanin Date: Wed, 1 Apr 2026 00:35:57 +0200 Subject: [PATCH 4/4] fix permissions --- .github/workflows/_local_on_pr.yml | 1 + .github/workflows/on-pr.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/_local_on_pr.yml b/.github/workflows/_local_on_pr.yml index e3da3c5..eaee419 100644 --- a/.github/workflows/_local_on_pr.yml +++ b/.github/workflows/_local_on_pr.yml @@ -23,3 +23,4 @@ jobs: uses: ./.github/workflows/on-pr.yml permissions: id-token: write + contents: read diff --git a/.github/workflows/on-pr.yml b/.github/workflows/on-pr.yml index 7976f4c..7c50b2b 100644 --- a/.github/workflows/on-pr.yml +++ b/.github/workflows/on-pr.yml @@ -16,6 +16,7 @@ # Attention: this workflow must be called with following permissions: # permissions: # id-token: write +# contents: read # The name will show up as "PR Checl / ๐Ÿ” / ", # so there is no reason to add any text where the icon is.