From ea46ad556b31f1bcd3e37f16fd84bf7f2fa92015 Mon Sep 17 00:00:00 2001
From: Evgeny Snitko <evgeny@parity.io>
Date: Tue, 28 May 2024 18:27:01 +0400
Subject: [PATCH] Conditional `required` checks (#4544)

Workaround for skipped but `required` github checks. The idea is to
trigger the workflow but filter out unaffected jobs or steps. See [ci_cd
998](https://github.com/paritytech/ci_cd/issues/988) for details

In `.github/workflows/check-changed-files.yml` there is a reusable
workflow thad does all the checks and publishes results as outputs.
Example usage:
```
jobs:
  changes:
    permissions:
      pull-requests: read
    uses: ./.github/workflows/check-changed-files.yml
  some-job:
    needs: changes
    if: ${{ needs.changes.outputs.rust }}
 .......
 ```
---
 .github/workflows/check-changed-files.yml | 57 +++++++++++++++++++++++
 .github/workflows/tests-linux-stable.yml  | 16 ++++++-
 .github/workflows/tests.yml               | 18 +++++--
 3 files changed, 86 insertions(+), 5 deletions(-)
 create mode 100644 .github/workflows/check-changed-files.yml

diff --git a/.github/workflows/check-changed-files.yml b/.github/workflows/check-changed-files.yml
new file mode 100644
index 00000000000..657c05cd047
--- /dev/null
+++ b/.github/workflows/check-changed-files.yml
@@ -0,0 +1,57 @@
+# Reusable workflow to perform checks and generate conditions for other workflows. 
+# Currently it checks if any Rust (build-related) file is changed
+# and if the current (caller) workflow file is changed.
+# Example:
+#
+# jobs:
+#   changes:
+#     permissions:
+#       pull-requests: read
+#     uses: ./.github/workflows/check-changed-files.yml
+#   some-job:
+#     needs: changes
+#     if: ${{ needs.changes.outputs.rust }}
+#  ....... 
+
+name: Check changes files
+
+on:
+  workflow_call:
+    # Map the workflow outputs to job outputs
+    outputs:
+      rust: 
+        value: ${{ jobs.changes.outputs.rust }}
+        description: 'true if any of the build-related OR current (caller) workflow files have changed'
+      current-workflow: 
+        value: ${{ jobs.changes.outputs.current-workflow }}
+        description: 'true if current (caller) workflow file has changed'      
+
+jobs:
+  changes:
+    runs-on: ubuntu-latest
+    permissions:
+      pull-requests: read
+    outputs:
+      # true if current workflow (caller) file is changed
+      rust: ${{ steps.filter.outputs.rust == 'true' || steps.filter.outputs.current-workflow == 'true' }}
+      current-workflow: ${{ steps.filter.outputs.current-workflow }}
+    steps:
+    - id: current-file
+      run: echo "current-workflow-file=$(echo ${{ github.workflow_ref }} | sed -nE "s/.*(\.github\/workflows\/[a-zA-Z0-9_-]*\.y[a]?ml)@refs.*/\1/p")" >> $GITHUB_OUTPUT
+    - run: echo "${{ steps.current-file.outputs.current-workflow-file }}"
+      # For pull requests it's not necessary to checkout the code
+    - id: filter
+      uses: dorny/paths-filter@v3
+      with:
+        predicate-quantifier: 'every'
+        # current-workflow - check if the current (caller) workflow file is changed
+        # rust - check if any Rust (build-related) file is changed
+        filters: |
+          current-workflow:
+            - '${{ steps.current-file.outputs.current-workflow-file }}'
+          rust:
+            - '**/*'
+            - '!.github/**/*'
+            - '!prdoc/**/*'
+            - '!docs/**/*'
+    #
\ No newline at end of file
diff --git a/.github/workflows/tests-linux-stable.yml b/.github/workflows/tests-linux-stable.yml
index 8822ba6d250..5fdfabc437f 100644
--- a/.github/workflows/tests-linux-stable.yml
+++ b/.github/workflows/tests-linux-stable.yml
@@ -20,10 +20,18 @@ env:
   FORKLIFT_metrics_pushEndpoint: ${{ secrets.FORKLIFT_metrics_pushEndpoint }}
 
 jobs:
+
+  changes:
+    permissions:
+      pull-requests: read
+    uses: ./.github/workflows/check-changed-files.yml
+
   set-image:
     # GitHub Actions allows using 'env' in a container context.
     # However, env variables don't work for forks: https://github.com/orgs/community/discussions/44322
     # This workaround sets the container image for each job using 'set-image' job output.
+    needs: changes
+    if: ${{ needs.changes.outputs.rust }}      
     runs-on: ubuntu-latest
     outputs:
       IMAGE: ${{ steps.set_image.outputs.IMAGE }}
@@ -32,10 +40,12 @@ jobs:
         uses: actions/checkout@v4
       - id: set_image
         run: cat .github/env >> $GITHUB_OUTPUT
+  
   test-linux-stable-int:
+    needs: [set-image, changes]
+    if: ${{ needs.changes.outputs.rust }}  
     runs-on: arc-runners-polkadot-sdk-beefy
     timeout-minutes: 30
-    needs: [set-image]
     container:
       image: ${{ needs.set-image.outputs.IMAGE }}
     env:
@@ -50,11 +60,13 @@ jobs:
         uses: actions/checkout@v4
       - name: script
         run: WASM_BUILD_NO_COLOR=1 time forklift cargo test -p staging-node-cli --release --locked -- --ignored
+  
   # https://github.com/paritytech/ci_cd/issues/864
   test-linux-stable-runtime-benchmarks:
+    needs: [set-image, changes]
+    if: ${{ needs.changes.outputs.rust }}    
     runs-on: arc-runners-polkadot-sdk-beefy
     timeout-minutes: 30
-    needs: [set-image]
     container:
       image: ${{ needs.set-image.outputs.IMAGE }}
     env:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 76bccba86b2..293acadc4e6 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -19,6 +19,12 @@ env:
   FORKLIFT_metrics_pushEndpoint: ${{ secrets.FORKLIFT_metrics_pushEndpoint }}
 
 jobs:
+
+  changes:
+    permissions:
+      pull-requests: read
+    uses: ./.github/workflows/check-changed-files.yml
+
   set-image:
     # GitHub Actions allows using 'env' in a container context.
     # However, env variables don't work for forks: https://github.com/orgs/community/discussions/44322
@@ -31,10 +37,12 @@ jobs:
         uses: actions/checkout@v4
       - id: set_image
         run: cat .github/env >> $GITHUB_OUTPUT
+
   quick-benchmarks:
+    needs: [set-image, changes]
+    if: ${{ needs.changes.outputs.rust }}    
     runs-on: arc-runners-polkadot-sdk-beefy
     timeout-minutes: 30
-    needs: [set-image]
     container:
       image: ${{ needs.set-image.outputs.IMAGE }}
     env:
@@ -47,11 +55,13 @@ jobs:
         uses: actions/checkout@v4
       - name: script
         run: time forklift cargo run --locked --release -p staging-node-cli --bin substrate-node --features runtime-benchmarks -- benchmark pallet --chain dev --pallet "*" --extrinsic "*" --steps 2 --repeat 1 --quiet
+  
   # cf https://github.com/paritytech/polkadot-sdk/issues/1652
   test-syscalls:
+    needs: [set-image, changes]
+    if: ${{ needs.changes.outputs.rust }}    
     runs-on: arc-runners-polkadot-sdk-beefy
     timeout-minutes: 30
-    needs: [set-image]
     container:
       image: ${{ needs.set-image.outputs.IMAGE }}
     continue-on-error: true # this rarely triggers in practice
@@ -71,10 +81,12 @@ jobs:
     # - if [[ "$CI_JOB_STATUS" == "failed" ]]; then
     #   printf "The x86_64 syscalls used by the worker binaries have changed. Please review if this is expected and update polkadot/scripts/list-syscalls/*-worker-syscalls as needed.\n";
     #   fi
+  
   cargo-check-all-benches:
+    needs: [set-image, changes]
+    if: ${{ needs.changes.outputs.rust }}    
     runs-on: arc-runners-polkadot-sdk-beefy
     timeout-minutes: 30
-    needs: [set-image]
     container:
       image: ${{ needs.set-image.outputs.IMAGE }}
     env:
-- 
GitLab