diff --git a/.github/actions/detect-relevant-changes/action.yaml b/.github/actions/detect-relevant-changes/action.yaml index 2b759029..99cec3f6 100644 --- a/.github/actions/detect-relevant-changes/action.yaml +++ b/.github/actions/detect-relevant-changes/action.yaml @@ -20,6 +20,10 @@ inputs: description: "Optional glob filters (comma or newline separated)" required: false default: "" + exclude-globs: + description: "Optional glob filters to exclude (comma or newline separated)" + required: false + default: "" type-pattern-add: description: >- Additional type-to-glob mappings (comma or newline separated, e.g. cpp:*.cc). '.in' variants are added @@ -45,6 +49,7 @@ runs: HEAD_REF: ${{ inputs.head-ref }} FILE_TYPE: ${{ inputs.file-type }} INCLUDE_GLOBS: ${{ inputs.include-globs }} + EXCLUDE_GLOBS: ${{ inputs.exclude-globs }} TYPE_PATTERN_ADD: ${{ inputs.type-pattern-add }} # yamllint disable rule:line-length run: | @@ -90,6 +95,7 @@ runs: mapfile -t REQUESTED_TYPES < <(parse_list "$FILE_TYPE") mapfile -t INCLUDE_PATTERNS < <(parse_list "$INCLUDE_GLOBS") + mapfile -t EXCLUDE_PATTERNS < <(parse_list "$EXCLUDE_GLOBS") if [ -z "$HEAD_REF" ]; then HEAD_REF=$(git rev-parse HEAD) @@ -159,22 +165,23 @@ runs: ALL_PATTERNS=() fi - FIND_CMD=(find . -type f) - if [ "${#ALL_PATTERNS[@]}" -gt 0 ]; then - FIND_CMD+=(\() - first=true - for pattern in "${ALL_PATTERNS[@]}"; do - if [ "$first" = true ]; then - first=false - else - FIND_CMD+=(-o) - fi - FIND_CMD+=(-name "$pattern") - done - FIND_CMD+=(\)) - fi - - "${FIND_CMD[@]}" | sed 's|^\./||' | LC_ALL=C sort > "$RUNNER_TEMP/find-matches.txt" + # Use git ls-tree instead of find so this works even when the working + # tree contains no files (e.g. after a sparse checkout with no patterns). + { + if [ "${#ALL_PATTERNS[@]}" -gt 0 ]; then + git ls-tree -r --name-only "${HEAD_REF}" | while IFS= read -r file; do + basename="${file##*/}" + for pattern in "${ALL_PATTERNS[@]}"; do + if [[ "$basename" == $pattern ]]; then + printf '%s\n' "$file" + break + fi + done + done + else + git ls-tree -r --name-only "${HEAD_REF}" + fi + } | LC_ALL=C sort > "$RUNNER_TEMP/find-matches.txt" LC_ALL=C sort "$RUNNER_TEMP/changed-files.txt" > "$RUNNER_TEMP/changed-files-sorted.txt" if [ -s "$RUNNER_TEMP/find-matches.txt" ]; then @@ -194,10 +201,19 @@ runs: return 1 } + filter_by_exclude() { + local file="$1" + for exclude_pattern in "${EXCLUDE_PATTERNS[@]}"; do + # $exclude_pattern intentionally unquoted to enable glob matching + [[ "$file" == $exclude_pattern ]] && return 1 + done + return 0 + } + : > "$RUNNER_TEMP/matched-files.txt" while IFS= read -r matched_file; do [ -z "$matched_file" ] && continue - if filter_by_include "$matched_file"; then + if filter_by_include "$matched_file" && filter_by_exclude "$matched_file"; then echo "$matched_file" >> "$RUNNER_TEMP/matched-files.txt" fi done < "$RUNNER_TEMP/initial-matched.txt" diff --git a/.github/actions/run-change-detection/action.yaml b/.github/actions/run-change-detection/action.yaml index 902bd854..4a3278f7 100644 --- a/.github/actions/run-change-detection/action.yaml +++ b/.github/actions/run-change-detection/action.yaml @@ -45,6 +45,10 @@ runs: ref: ${{ inputs.ref }} repository: ${{ inputs.repo }} persist-credentials: false + # Use empty sparse checkout so no PR files are materialized in the working + # tree — only git objects are needed for diff and ls-tree operations. + sparse-checkout-cone-mode: false + sparse-checkout: "" - name: Detect relevant changes id: filter diff --git a/.github/workflows/actionlint-check.yaml b/.github/workflows/actionlint-check.yaml index 4236c799..ea6e24a5 100644 --- a/.github/workflows/actionlint-check.yaml +++ b/.github/workflows/actionlint-check.yaml @@ -87,15 +87,18 @@ jobs: ref: ${{ needs.setup.outputs.ref }} path: ${{ needs.setup.outputs.checkout_path }} repository: ${{ needs.setup.outputs.repo }} + persist-credentials: false - name: Announce actionlint check run: echo "➡️ Running actionlint check..." - name: Run actionlint id: lint + env: + CHECKOUT_PATH: ${{ needs.setup.outputs.checkout_path }} run: | docker run --rm \ - -v "${{ github.workspace }}/${{ needs.setup.outputs.checkout_path }}:/work" \ + -v "$GITHUB_WORKSPACE/${CHECKOUT_PATH}:/work" \ -w /work \ rhysd/actionlint:latest \ -config-file .github/actionlint.yaml diff --git a/.github/workflows/clang-format-check.yaml b/.github/workflows/clang-format-check.yaml index f385f740..ae73a006 100644 --- a/.github/workflows/clang-format-check.yaml +++ b/.github/workflows/clang-format-check.yaml @@ -47,6 +47,7 @@ jobs: ref: ${{ needs.setup.outputs.ref }} path: ${{ needs.setup.outputs.checkout_path }} repository: ${{ needs.setup.outputs.repo }} + persist-credentials: false - name: Announce clang-format check run: echo "➡️ Running clang-format check..." @@ -62,11 +63,14 @@ jobs: - name: Evaluate clang-format result if: always() && steps.lint.outcome != 'skipped' + env: + REPO: ${{ needs.setup.outputs.repo }} run: | + REPO_NAME="${REPO##*/}" if [ "${{ steps.lint.outcome }}" = 'success' ]; then echo "✅ clang-format check passed." else echo "::error::clang-format check failed. Please review the output above for details." - echo "::error::Comment '@${{ github.event.repository.name }}bot format' on the PR to attempt auto-fix." + echo "::error::Comment '@${REPO_NAME}bot format' on the PR to attempt auto-fix." exit 1 fi diff --git a/.github/workflows/clang-tidy-check.yaml b/.github/workflows/clang-tidy-check.yaml index 921a5c01..50f64ab6 100644 --- a/.github/workflows/clang-tidy-check.yaml +++ b/.github/workflows/clang-tidy-check.yaml @@ -59,6 +59,7 @@ jobs: ref: ${{ needs.setup.outputs.ref }} path: ${{ needs.setup.outputs.checkout_path }} repository: ${{ needs.setup.outputs.repo }} + persist-credentials: false - name: Setup build environment uses: Framework-R-D/phlex/.github/actions/setup-build-env@main @@ -78,20 +79,28 @@ jobs: - name: Run clang-tidy using CMake id: tidy shell: bash + working-directory: ${{ needs.setup.outputs.build_path }} + env: + REPO: ${{ needs.setup.outputs.repo }} run: | . /entrypoint.sh - cd "$GITHUB_WORKSPACE/${{ needs.setup.outputs.build_path }}" + REPO_NAME="${REPO##*/}" echo "➡️ Running clang-tidy checks..." cmake_status=0 cmake --build . -j "$(nproc)" > clang-tidy.log 2>&1 || cmake_status=$? if [ "$cmake_status" -ne 0 ]; then - echo "::error::CMake build failed with exit code $cmake_status" - exit 1 - elif grep -qE '^/.+\.(cpp|hpp|c|h):[0-9]+:[0-9]+: (warning|error):' clang-tidy.log; then + echo "::error::clang-tidy CMake build failed (exit code $cmake_status)" + echo "::group::clang-tidy log output" + cat clang-tidy.log + echo "::endgroup::" + exit "$cmake_status" + fi + + if grep -qE '^/.+\.(cpp|hpp|c|h):[0-9]+:[0-9]+: (warning|error):' clang-tidy.log; then echo "::warning::Clang-tidy found issues in the code" - exit 1 + echo "Comment '@${REPO_NAME}bot tidy-fix [...]' on the PR to attempt auto-fix" else echo "✅ clang-tidy check passed" fi diff --git a/.github/workflows/clang-tidy-fix.yaml b/.github/workflows/clang-tidy-fix.yaml index 88e41e7f..c35e5273 100644 --- a/.github/workflows/clang-tidy-fix.yaml +++ b/.github/workflows/clang-tidy-fix.yaml @@ -52,7 +52,8 @@ jobs: env: COMMENT_BODY: ${{ github.event.comment.body }} run: | - bot_name="${{ github.event.repository.name }}bot" + REPO_NAME="${GITHUB_REPOSITORY##*/}" + bot_name="${REPO_NAME}bot" checks_line=$(echo "$COMMENT_BODY" | sed -nE "s/^@${bot_name}[[:space:]]+tidy-fix[[:space:]]+(.*)/\1/p" | tr -d '\r') if [ -n "$checks_line" ]; then @@ -110,12 +111,20 @@ jobs: if: needs.setup.outputs.tidy_checks == '' && (steps.download_fixes_check.outcome == 'success' || steps.download_fixes_fix.outcome == 'success') + env: + CHECKOUT_PATH: ${{ needs.setup.outputs.checkout_path }} run: | - if [ -f fixes/clang-tidy-fixes.yaml ]; then + # The artifact preserves the build directory prefix in its path structure. + FIXES_FILE="" + if [ -d fixes ]; then + FIXES_FILE=$(find fixes -name "clang-tidy-fixes.yaml" | head -1) + fi + if [ -n "$FIXES_FILE" ]; then echo "Applying fixes from existing artifact..." . /entrypoint.sh - cd "${{ needs.setup.outputs.checkout_path }}" - clang-apply-replacements ../fixes || true + FIXES_DIR="$(realpath "${FIXES_FILE%/*}")" + cd "${CHECKOUT_PATH}" + clang-apply-replacements "${FIXES_DIR}" || true echo "applied=true" >> "$GITHUB_OUTPUT" else echo "applied=false" >> "$GITHUB_OUTPUT" @@ -156,16 +165,20 @@ jobs: - name: Generate clang-tidy fixes using CMake build if: steps.apply_from_artifact.outputs.applied != 'true' + env: + BUILD_PATH: ${{ needs.setup.outputs.build_path }} run: | . /entrypoint.sh - cd "$GITHUB_WORKSPACE/${{ needs.setup.outputs.build_path }}" + cd "$GITHUB_WORKSPACE/${BUILD_PATH}" cmake --build . -j "$(nproc)" || true - name: Apply clang-tidy fixes if: steps.apply_from_artifact.outputs.applied != 'true' + env: + BUILD_PATH: ${{ needs.setup.outputs.build_path }} run: | . /entrypoint.sh - cd "$GITHUB_WORKSPACE/${{ needs.setup.outputs.build_path }}" + cd "$GITHUB_WORKSPACE/${BUILD_PATH}" if [ -f clang-tidy-fixes.yaml ]; then clang-apply-replacements . || true fi @@ -195,6 +208,7 @@ jobs: runs-on: ubuntu-latest permissions: pull-requests: write + issues: write steps: - name: Post Clang-Tidy results uses: Framework-R-D/phlex/.github/actions/post-clang-tidy-results@main diff --git a/.github/workflows/cmake-build.yaml b/.github/workflows/cmake-build.yaml index 8530ffff..3b2535f3 100644 --- a/.github/workflows/cmake-build.yaml +++ b/.github/workflows/cmake-build.yaml @@ -143,6 +143,7 @@ jobs: path: ${{ needs.setup.outputs.checkout_path }} ref: ${{ needs.setup.outputs.ref }} repository: ${{ needs.setup.outputs.repo }} + persist-credentials: false - name: Setup build environment uses: Framework-R-D/phlex/.github/actions/setup-build-env@main @@ -178,9 +179,11 @@ jobs: - name: Run tests if: matrix.sanitizer != 'valgrind' + env: + BUILD_PATH: ${{ needs.setup.outputs.build_path }} run: | . /entrypoint.sh - cd "$GITHUB_WORKSPACE/${{ needs.setup.outputs.build_path }}" + cd "$GITHUB_WORKSPACE/${BUILD_PATH}" echo "➡️ Running tests..." echo "::group::Running ctest" @@ -195,9 +198,11 @@ jobs: - name: Run Valgrind tests if: matrix.sanitizer == 'valgrind' + env: + BUILD_PATH: ${{ needs.setup.outputs.build_path }} run: | . /entrypoint.sh - cd "$GITHUB_WORKSPACE/${{ needs.setup.outputs.build_path }}" + cd "$GITHUB_WORKSPACE/${BUILD_PATH}" echo "➡️ Running Valgrind tests..." echo "::group::Running ctest -T memcheck" diff --git a/.github/workflows/cmake-format-check.yaml b/.github/workflows/cmake-format-check.yaml index 8a7eb5ed..fe6ae076 100644 --- a/.github/workflows/cmake-format-check.yaml +++ b/.github/workflows/cmake-format-check.yaml @@ -80,6 +80,7 @@ jobs: ref: ${{ needs.setup.outputs.ref }} path: ${{ needs.setup.outputs.checkout_path }} repository: ${{ needs.setup.outputs.repo }} + persist-credentials: false - name: Set up Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 @@ -91,20 +92,25 @@ jobs: - name: Check CMake formatting id: lint + env: + CHECKOUT_PATH: ${{ needs.setup.outputs.checkout_path }} run: | echo "➡️ Checking CMake file formatting..." - gersemi --check ${{ needs.setup.outputs.checkout_path }} + gersemi --check "${CHECKOUT_PATH}" continue-on-error: true - name: Evaluate CMake formatting result if: always() && steps.lint.outcome != 'skipped' + env: + REPO: ${{ needs.setup.outputs.repo }} # yamllint disable rule:line-length run: | + REPO_NAME="${REPO##*/}" if [ "${{ steps.lint.outcome }}" = 'success' ]; then echo "✅ All CMake files are properly formatted." else echo "::error::Found files with formatting issues." - echo "::error::Run 'gersemi -i ' locally or comment '@${{ github.event.repository.name }}bot format' on the PR to auto-fix." + echo "::error::Run 'gersemi -i ' locally or comment '@${REPO_NAME}bot format' on the PR to auto-fix." exit 1 fi # yamllint enable diff --git a/.github/workflows/cmake-format-fix.yaml b/.github/workflows/cmake-format-fix.yaml index 57405a87..2bafb972 100644 --- a/.github/workflows/cmake-format-fix.yaml +++ b/.github/workflows/cmake-format-fix.yaml @@ -108,9 +108,10 @@ jobs: run: pip install gersemi - name: Apply CMake formatting + working-directory: ${{ needs.setup.outputs.checkout_path }} run: | echo "Applying CMake formatting..." - gersemi -i ${{ needs.setup.outputs.checkout_path }} + gersemi -i . - name: Handle fix commit id: handle_commit diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index 2dc15c0a..1a6dc9ff 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -93,12 +93,15 @@ jobs: - name: Determine if detection should be skipped id: should_skip + env: + IS_ACT: ${{ steps.setup.outputs.is_act }} + LANGUAGE_MATRIX: ${{ inputs.language-matrix }} run: | - if [ "${{ github.event_name }}" = "schedule" ] || \ - [ "${{ github.event_name }}" = "workflow_dispatch" ] || \ - [ "${{ github.event_name }}" = "push" ] || \ - { [ "${{ github.event_name }}" = "workflow_call" ] && [ -n "${{ inputs.language-matrix }}" ]; } || \ - [ "${{ steps.setup.outputs.is_act }}" = "true" ]; then + if [ "${GITHUB_EVENT_NAME}" = "schedule" ] || \ + [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ] || \ + [ "${GITHUB_EVENT_NAME}" = "push" ] || \ + { [ "${GITHUB_EVENT_NAME}" = "workflow_call" ] && [ -n "${LANGUAGE_MATRIX}" ]; } || \ + [ "${IS_ACT}" = "true" ]; then echo "skip=true" >> "$GITHUB_OUTPUT" else echo "skip=false" >> "$GITHUB_OUTPUT" @@ -157,16 +160,20 @@ jobs: id: build_matrix env: LANGUAGE_MATRIX: ${{ inputs.language-matrix }} + SKIP_DETECTION: ${{ needs.setup.outputs.skip_detection }} + HAS_CHANGES_CPP: ${{ needs.setup.outputs.has_changes_cpp }} + HAS_CHANGES_PYTHON: ${{ needs.setup.outputs.has_changes_python }} + HAS_CHANGES_ACTIONS: ${{ needs.setup.outputs.has_changes_actions }} run: | # If detection was skipped, use all languages or the provided language-matrix - if [ "${{ needs.setup.outputs.skip_detection }}" = "true" ]; then - if [ "${{ github.event_name }}" = "workflow_call" ] && [ -n "$LANGUAGE_MATRIX" ]; then + if [ "${SKIP_DETECTION}" = "true" ]; then + if [ "${GITHUB_EVENT_NAME}" = "workflow_call" ] && [ -n "${LANGUAGE_MATRIX}" ]; then # Validate that language-matrix is valid JSON - if ! echo "$LANGUAGE_MATRIX" | python3 -c "import sys, json; json.load(sys.stdin)" 2>/dev/null; then + if ! echo "${LANGUAGE_MATRIX}" | python3 -c "import sys, json; json.load(sys.stdin)" 2>/dev/null; then echo "::error::Invalid language-matrix input: must be valid JSON array" exit 1 fi - echo "languages=$LANGUAGE_MATRIX" >> "$GITHUB_OUTPUT" + echo "languages=${LANGUAGE_MATRIX}" >> "$GITHUB_OUTPUT" else echo 'languages=["cpp", "python", "actions"]' >> "$GITHUB_OUTPUT" fi @@ -175,13 +182,13 @@ jobs: # Build array based on detection results langs=() - if [ "${{ needs.setup.outputs.has_changes_cpp }}" = "true" ]; then + if [ "${HAS_CHANGES_CPP}" = "true" ]; then langs+=("cpp") fi - if [ "${{ needs.setup.outputs.has_changes_python }}" = "true" ]; then + if [ "${HAS_CHANGES_PYTHON}" = "true" ]; then langs+=("python") fi - if [ "${{ needs.setup.outputs.has_changes_actions }}" = "true" ]; then + if [ "${HAS_CHANGES_ACTIONS}" = "true" ]; then langs+=("actions") fi @@ -310,18 +317,21 @@ jobs: - name: Check CodeQL SARIF for new or resolved alerts id: check_codeql + env: + LOG_PATH: ${{ steps.set_log_path.outputs.path }} + INPUT_PR_NUMBER: ${{ inputs.pr-number }} run: | set -eu ARGS=( --sarif "$GITHUB_WORKSPACE/sarif" --min-level "${CODEQL_MIN_LEVEL}" - --log-path "${{ steps.set_log_path.outputs.path }}" + --log-path "${LOG_PATH}" ) PR_NUMBER="" - if [ "${{ github.event_name }}" = "pull_request" ]; then - PR_NUMBER="${{ github.event.pull_request.number }}" - elif [ "${{ github.event_name }}" = "workflow_call" ]; then - PR_NUMBER="${{ inputs.pr-number }}" + if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then + PR_NUMBER="$(jq -r '.pull_request.number // empty' "${GITHUB_EVENT_PATH}")" + elif [ "${GITHUB_EVENT_NAME}" = "workflow_call" ]; then + PR_NUMBER="${INPUT_PR_NUMBER}" fi if [ -n "$PR_NUMBER" ]; then @@ -329,7 +339,7 @@ jobs: fi script_path="scripts/check_codeql_alerts.py" - if [ "${{ github.event_name }}" = "workflow_call" ]; then + if [ "${GITHUB_EVENT_NAME}" = "workflow_call" ]; then script_path="phlex/$script_path" fi python3 "$script_path" "${ARGS[@]}" @@ -345,10 +355,12 @@ jobs: - name: Prepare PR comment data if: >- github.event_name == 'pull_request' && steps.check_codeql.outputs.comment_path != '' + env: + COMMENT_PATH: ${{ steps.check_codeql.outputs.comment_path }} run: | mkdir -p pr_comment_data - echo "${{ github.event.pull_request.number }}" > pr_comment_data/pr_number.txt - cp "${{ steps.check_codeql.outputs.comment_path }}" pr_comment_data/comment_body.md + jq -r '.pull_request.number // empty' "${GITHUB_EVENT_PATH}" > pr_comment_data/pr_number.txt + cp "${COMMENT_PATH}" pr_comment_data/comment_body.md - name: Upload PR comment data if: >- diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 084c4e82..71c48725 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -90,14 +90,13 @@ jobs: id: coverage_options shell: bash # yamllint disable rule:line-length + env: + REQUESTED_COMPILER: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs['phlex-coverage-compiler'] || '' }} + REQUESTED_FORM: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs['phlex-enable-form'] || '' }} run: | set -euo pipefail - requested_compiler="${{ github.event_name == 'workflow_dispatch' && github.event.inputs['phlex-coverage-compiler'] || '' }}" - default_compiler="clang" - requested_form="${{ github.event_name == 'workflow_dispatch' && github.event.inputs['phlex-enable-form'] || '' }}" - default_form="ON" - compiler="${requested_compiler:-$default_compiler}" - form="${requested_form:-$default_form}" + compiler="${REQUESTED_COMPILER:-clang}" + form="${REQUESTED_FORM:-ON}" echo "compiler=$compiler" >> "$GITHUB_OUTPUT" echo "enable_form=$form" >> "$GITHUB_OUTPUT" # yamllint enable @@ -108,6 +107,7 @@ jobs: ref: ${{ needs.setup.outputs.ref }} path: ${{ needs.setup.outputs.checkout_path }} repository: ${{ needs.setup.outputs.repo }} + persist-credentials: false - name: Setup build environment uses: Framework-R-D/phlex/.github/actions/setup-build-env@main @@ -144,8 +144,10 @@ jobs: - name: Unknown Compiler Error if: ${{ steps.coverage_options.outputs.compiler != 'gcc' && steps.coverage_options.outputs.compiler != 'clang' }} + env: + COMPILER: ${{ steps.coverage_options.outputs.compiler }} run: | - echo "ERROR: Unknown compiler '${{ steps.coverage_options.outputs.compiler }}'. Must be 'gcc' or 'clang'." + echo "ERROR: Unknown compiler '${COMPILER}'. Must be 'gcc' or 'clang'." exit 1 - name: Announce build @@ -158,12 +160,14 @@ jobs: build-path: ${{ needs.setup.outputs.build_path }} - name: Run tests with coverage + env: + BUILD_PATH: ${{ needs.setup.outputs.build_path }} run: | . /entrypoint.sh - cd "$GITHUB_WORKSPACE/${{ needs.setup.outputs.build_path }}" + cd "$GITHUB_WORKSPACE/${BUILD_PATH}" echo "➡️ Running tests with coverage..." - PROFILE_ROOT="$GITHUB_WORKSPACE/${{ needs.setup.outputs.build_path }}/test/profraw" + PROFILE_ROOT="$GITHUB_WORKSPACE/${BUILD_PATH}/test/profraw" echo "Cleaning LLVM profile directory: $PROFILE_ROOT" rm -rf "$PROFILE_ROOT" mkdir -p "$PROFILE_ROOT" @@ -183,9 +187,11 @@ jobs: id: report_gcc if: ${{ steps.coverage_options.outputs.compiler == 'gcc' }} shell: bash + env: + BUILD_PATH: ${{ needs.setup.outputs.build_path }} run: | . /entrypoint.sh - cd "$GITHUB_WORKSPACE/${{ needs.setup.outputs.build_path }}" + cd "$GITHUB_WORKSPACE/${BUILD_PATH}" echo "➡️ Generating coverage reports for GCC..." echo "::group::Running coverage-gcov target" @@ -202,9 +208,11 @@ jobs: id: report_clang if: ${{ steps.coverage_options.outputs.compiler == 'clang' }} shell: bash + env: + BUILD_PATH: ${{ needs.setup.outputs.build_path }} run: | . /entrypoint.sh - cd "$GITHUB_WORKSPACE/${{ needs.setup.outputs.build_path }}" + cd "$GITHUB_WORKSPACE/${BUILD_PATH}" echo "➡️ Generating coverage reports for Clang..." echo "::group::Running coverage-llvm target" @@ -221,9 +229,11 @@ jobs: id: report_python if: ${{ steps.report_gcc.outcome != 'skipped' || steps.report_clang.outcome != 'skipped' }} shell: bash + env: + BUILD_PATH: ${{ needs.setup.outputs.build_path }} run: | . /entrypoint.sh - cd "$GITHUB_WORKSPACE/${{ needs.setup.outputs.build_path }}" + cd "$GITHUB_WORKSPACE/${BUILD_PATH}" echo "➡️ Generating Python coverage report..." echo "::group::Running coverage-python target" @@ -246,8 +256,10 @@ jobs: id: coverage_outputs if: ${{ steps.report_gcc.outcome != 'skipped' || steps.report_clang.outcome != 'skipped' }} shell: bash + env: + BUILD_PATH: ${{ needs.setup.outputs.build_path }} run: | - cd "$GITHUB_WORKSPACE/${{ needs.setup.outputs.build_path }}" + cd "$GITHUB_WORKSPACE/${BUILD_PATH}" if [ -f coverage.xml ]; then echo "has_coverage_xml=true" >> "$GITHUB_OUTPUT" else @@ -278,12 +290,14 @@ jobs: - name: Prepare coverage artifact bundle if: ${{ steps.report_gcc.outcome != 'skipped' || steps.report_clang.outcome != 'skipped' }} shell: bash + env: + BUILD_PATH: ${{ needs.setup.outputs.build_path }} run: | set -euo pipefail ARTIFACT_DIR="$GITHUB_WORKSPACE/coverage-artifacts" rm -rf "$ARTIFACT_DIR" mkdir -p "$ARTIFACT_DIR" - cd "$GITHUB_WORKSPACE/${{ needs.setup.outputs.build_path }}" + cd "$GITHUB_WORKSPACE/${BUILD_PATH}" for file in \ coverage-llvm.txt \ coverage-llvm.info \ diff --git a/.github/workflows/dependabot-auto-merge.yaml b/.github/workflows/dependabot-auto-merge.yaml index d9f6100b..61ff9d02 100644 --- a/.github/workflows/dependabot-auto-merge.yaml +++ b/.github/workflows/dependabot-auto-merge.yaml @@ -28,14 +28,17 @@ jobs: steps: - name: Get PR details id: pr + # jq's // empty alternative operator returns an empty string instead of + # the literal "null" when a key is absent or null in the event payload. + # This ensures the downstream empty/null/numeric checks work correctly. run: | - if [ "${{ github.event_name }}" = "check_suite" ]; then - PR_NUMBER="${{ github.event.check_suite.pull_requests[0].number }}" + if [ "${GITHUB_EVENT_NAME}" = "check_suite" ]; then + PR_NUMBER="$(jq -r '.check_suite.pull_requests[0].number // empty' "${GITHUB_EVENT_PATH}")" if [ -z "$PR_NUMBER" ] || [ "$PR_NUMBER" = "null" ] || ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then echo "No valid PR number found in check_suite event (got: $PR_NUMBER)" exit 1 fi - PR_JSON=$(gh pr view "$PR_NUMBER" --repo "${{ github.repository }}" --json author,baseRefName) + PR_JSON=$(gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json author,baseRefName) AUTHOR=$(echo "$PR_JSON" | jq -r '.author.login') BASE_REF=$(echo "$PR_JSON" | jq -r '.baseRefName') @@ -47,9 +50,9 @@ jobs: else # For pull_request_target and pull_request_review, use event data { - echo "author=${{ github.event.pull_request.user.login }}" - echo "base_ref=${{ github.event.pull_request.base.ref }}" - echo "number=${{ github.event.pull_request.number }}" + echo "author=$(jq -r '.pull_request.user.login // empty' "${GITHUB_EVENT_PATH}")" + echo "base_ref=$(jq -r '.pull_request.base.ref // empty' "${GITHUB_EVENT_PATH}")" + echo "number=$(jq -r '.pull_request.number // empty' "${GITHUB_EVENT_PATH}")" } >> "$GITHUB_OUTPUT" fi env: @@ -58,10 +61,13 @@ jobs: - name: Enable auto-merge for Dependabot PRs if: steps.pr.outputs.author == 'dependabot[bot]' && steps.pr.outputs.base_ref == 'main' shell: bash + env: + PR_NUMBER: ${{ steps.pr.outputs.number }} + GH_TOKEN: ${{ secrets.WORKFLOW_PAT }} # yamllint disable rule:line-length run: | set -o pipefail - if ! gh pr merge --auto --rebase "${{ steps.pr.outputs.number }}" --repo "${{ github.repository }}" 2>&1 | tee /tmp/gh-output.txt; then + if ! gh pr merge --auto --rebase "${PR_NUMBER}" --repo "$GITHUB_REPOSITORY" 2>&1 | tee /tmp/gh-output.txt; then if grep -qE "auto-merge is already enabled|[Rr]equired.*status.*check|[Rr]equired approving review|[Rr]equired.*review" /tmp/gh-output.txt; then echo "Auto-merge not enabled yet - this is expected when requirements are not met or already enabled" exit 0 @@ -72,5 +78,3 @@ jobs: fi fi # yamllint enable - env: - GH_TOKEN: ${{ secrets.WORKFLOW_PAT }} diff --git a/.github/workflows/header-guards-check.yaml b/.github/workflows/header-guards-check.yaml index 42bd4762..59b76581 100644 --- a/.github/workflows/header-guards-check.yaml +++ b/.github/workflows/header-guards-check.yaml @@ -83,6 +83,7 @@ jobs: ref: ${{ needs.setup.outputs.ref }} path: ${{ needs.setup.outputs.checkout_path }} repository: ${{ needs.setup.outputs.repo }} + persist-credentials: false - name: Set up Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 @@ -98,7 +99,10 @@ jobs: - name: Report results if: always() && steps.check.outputs.has_issues == 'true' + env: + REPO: ${{ needs.setup.outputs.repo }} run: | + REPO_NAME="${REPO##*/}" echo "::error::Header guard check failed." - echo "::error::Comment '@${{ github.event.repository.name }}bot header-guards-fix' on the PR to auto-fix." + echo "::error::Comment '@${REPO_NAME}bot header-guards-fix' on the PR to auto-fix." exit 1 diff --git a/.github/workflows/jsonnet-format-check.yaml b/.github/workflows/jsonnet-format-check.yaml index 476c5350..5e5b9fa7 100644 --- a/.github/workflows/jsonnet-format-check.yaml +++ b/.github/workflows/jsonnet-format-check.yaml @@ -83,6 +83,7 @@ jobs: ref: ${{ needs.setup.outputs.ref }} repository: ${{ needs.setup.outputs.repo }} path: ${{ needs.setup.outputs.checkout_path }} + persist-credentials: false - name: Check Jsonnet formatting id: lint @@ -94,13 +95,16 @@ jobs: - name: Evaluate Jsonnet formatting result if: always() && steps.lint.outcome != 'skipped' + env: + REPO: ${{ needs.setup.outputs.repo }} # yamllint disable rule:line-length run: | + REPO_NAME="${REPO##*/}" if [ "${{ steps.lint.outcome }}" = 'success' ]; then echo "✅ Jsonnet formatting check passed." else echo "::error::Jsonnet formatting issues found. Please review the output above for details." - echo "::error::Run 'jsonnetfmt -i ' locally or comment '@${{ github.event.repository.name }}bot format' on the PR to auto-fix." + echo "::error::Run 'jsonnetfmt -i ' locally or comment '@${REPO_NAME}bot format' on the PR to auto-fix." exit 1 fi # yamllint enable diff --git a/.github/workflows/jsonnet-format-fix.yaml b/.github/workflows/jsonnet-format-fix.yaml index fc433b45..fa730ca1 100644 --- a/.github/workflows/jsonnet-format-fix.yaml +++ b/.github/workflows/jsonnet-format-fix.yaml @@ -106,7 +106,7 @@ jobs: CHECKOUT_PATH: ${{ needs.setup.outputs.checkout_path }} # yamllint disable rule:line-length run: | - docker run --rm -v "${{ github.workspace }}:/work" -w /work --user root public.ecr.aws/bitnami/jsonnet:latest \ + docker run --rm -v "$GITHUB_WORKSPACE:/work" -w /work --user root public.ecr.aws/bitnami/jsonnet:latest \ sh -c "find \"$CHECKOUT_PATH\" \( -name '*.jsonnet' -o -name '*.libsonnet' \) -print0 | xargs -0 -r jsonnetfmt -i" # yamllint enable continue-on-error: true diff --git a/.github/workflows/markdown-check.yaml b/.github/workflows/markdown-check.yaml index 1968e927..743d35b4 100644 --- a/.github/workflows/markdown-check.yaml +++ b/.github/workflows/markdown-check.yaml @@ -83,6 +83,7 @@ jobs: ref: ${{ needs.setup.outputs.ref }} path: ${{ needs.setup.outputs.checkout_path }} repository: ${{ needs.setup.outputs.repo }} + persist-credentials: false - name: Add problem matcher uses: xt0rted/markdownlint-problem-matcher@1a5fabfb577370cfdf5af944d418e4be3ea06f27 # v3.0.0 @@ -98,13 +99,16 @@ jobs: - name: Evaluate markdownlint result if: always() && steps.lint.outcome != 'skipped' + env: + REPO: ${{ needs.setup.outputs.repo }} # yamllint disable rule:line-length run: | + REPO_NAME="${REPO##*/}" if [ "${{ steps.lint.outcome }}" = "success" ]; then echo "✅ Markdown formatting check passed." else echo "::error::Markdown formatting check failed." - echo "::error::Comment '@${{ github.event.repository.name }}bot format' or '@${{ github.event.repository.name }}bot markdown-fix' on the PR to auto-fix." + echo "::error::Comment '@${REPO_NAME}bot format' or '@${REPO_NAME}bot markdown-fix' on the PR to auto-fix." exit 1 fi # yamllint enable diff --git a/.github/workflows/python-check.yaml b/.github/workflows/python-check.yaml index d4eda96b..0cdd5b2f 100644 --- a/.github/workflows/python-check.yaml +++ b/.github/workflows/python-check.yaml @@ -83,6 +83,7 @@ jobs: ref: ${{ needs.setup.outputs.ref }} path: ${{ needs.setup.outputs.checkout_path }} repository: ${{ needs.setup.outputs.repo }} + persist-credentials: false - name: Set up Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 @@ -113,12 +114,15 @@ jobs: - name: Evaluate Python checks result if: always() && (steps.ruff.outcome != 'skipped' || steps.mypy.outcome != 'skipped') + env: + REPO: ${{ needs.setup.outputs.repo }} # yamllint disable rule:line-length run: | + REPO_NAME="${REPO##*/}" if [ "${{ steps.ruff.outcome }}" = 'success' ] && [ "${{ steps.mypy.outcome }}" = 'success' ]; then echo "✅ Python checks passed." else - echo "::error::Python checks failed. Comment '@${{ github.event.repository.name }}bot python-fix' on the PR to attempt auto-fix." + echo "::error::Python checks failed. Comment '@${REPO_NAME}bot python-fix' on the PR to attempt auto-fix." exit 1 fi # yamllint enable diff --git a/.github/workflows/yaml-check.yaml b/.github/workflows/yaml-check.yaml index 05c41ed2..cc5d49c7 100644 --- a/.github/workflows/yaml-check.yaml +++ b/.github/workflows/yaml-check.yaml @@ -43,6 +43,7 @@ jobs: ref: ${{ needs.setup.outputs.ref }} path: ${{ needs.setup.outputs.checkout_path }} repository: ${{ needs.setup.outputs.repo }} + persist-credentials: false - name: Setup Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 @@ -60,11 +61,14 @@ jobs: - name: Evaluate yamllint result if: always() && steps.lint.outcome != 'skipped' + env: + REPO: ${{ needs.setup.outputs.repo }} run: | + REPO_NAME="${REPO##*/}" if [ "${{ steps.lint.outcome }}" = "success" ]; then echo "✅ YAML check passed." else echo "::error::YAML check failed." - echo "::error::Comment '@${{ github.event.repository.name }}bot yaml-fix' on the PR to auto-fix." + echo "::error::Comment '@${REPO_NAME}bot yaml-fix' on the PR to auto-fix." exit 1 fi diff --git a/.github/workflows/yaml-fix.yaml b/.github/workflows/yaml-fix.yaml index 7a46c75f..b3f2e519 100644 --- a/.github/workflows/yaml-fix.yaml +++ b/.github/workflows/yaml-fix.yaml @@ -109,8 +109,8 @@ jobs: run: npm install -g prettier - name: Apply YAML formatting + working-directory: ${{ needs.setup.outputs.checkout_path }} run: | - cd ${{ needs.setup.outputs.checkout_path }} prettier --write '**/*.{yaml,yml}' - name: Handle fix commit