name: Reusable change detection on: # yamllint disable-line rule:truthy workflow_call: outputs: # Some of the referenced steps set outputs conditionally and there may be # cases when referencing them evaluates to empty strings. It is nice to # work with proper booleans so they have to be evaluated through JSON # conversion in the expressions. However, empty strings used like that # may trigger all sorts of undefined and hard-to-debug behaviors in # GitHub Actions CI/CD. To help with this, all of the outputs set here # that are meant to be used as boolean flags (and not arbitrary strings), # MUST have fallbacks with default values set. A common pattern would be # to add ` || false` to all such expressions here, in the output # definitions. They can then later be safely used through the following # idiom in job conditionals and other expressions. Here's some examples: # # if: fromJSON(needs.change-detection.outputs.run-docs) # # ${{ # fromJSON(needs.change-detection.outputs.run-tests) # && 'truthy-branch' # || 'falsy-branch' # }} # config_hash: description: Config hash value for use in cache keys value: ${{ jobs.compute-changes.outputs.config-hash }} # str run-docs: description: Whether to build the docs value: ${{ jobs.compute-changes.outputs.run-docs || false }} # bool run_tests: description: Whether to run the regular tests value: ${{ jobs.compute-changes.outputs.run-tests || false }} # bool run-win-msi: description: Whether to run the MSI installer smoke tests value: >- # bool ${{ jobs.compute-changes.outputs.run-win-msi || false }} run_hypothesis: description: Whether to run the Hypothesis tests value: >- # bool ${{ jobs.compute-changes.outputs.run-hypothesis || false }} run_cifuzz: description: Whether to run the CIFuzz job value: >- # bool ${{ jobs.compute-changes.outputs.run-cifuzz || false }} jobs: compute-changes: name: Compute changed files runs-on: ubuntu-latest timeout-minutes: 10 outputs: config-hash: ${{ steps.config-hash.outputs.hash }} run-cifuzz: ${{ steps.check.outputs.run-cifuzz }} run-docs: ${{ steps.docs-changes.outputs.run-docs }} run-hypothesis: ${{ steps.check.outputs.run-hypothesis }} run-tests: ${{ steps.check.outputs.run-tests }} run-win-msi: ${{ steps.win-msi-changes.outputs.run-win-msi }} steps: - run: >- echo '${{ github.event_name }}' - uses: actions/checkout@v4 - name: Check for source changes id: check run: | if [ -z "$GITHUB_BASE_REF" ]; then echo "run-tests=true" >> $GITHUB_OUTPUT else git fetch origin $GITHUB_BASE_REF --depth=1 # git diff "origin/$GITHUB_BASE_REF..." (3 dots) may be more # reliable than git diff "origin/$GITHUB_BASE_REF.." (2 dots), # but it requires to download more commits (this job uses # "git fetch --depth=1"). # # git diff "origin/$GITHUB_BASE_REF..." (3 dots) works with Git # 2.26, but Git 2.28 is stricter and fails with "no merge base". # # git diff "origin/$GITHUB_BASE_REF.." (2 dots) should be enough on # GitHub, since GitHub starts by merging origin/$GITHUB_BASE_REF # into the PR branch anyway. # # https://github.com/python/core-workflow/issues/373 git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qvE '(\.rst$|^Doc|^Misc|^\.pre-commit-config\.yaml$|\.ruff\.toml$|\.md$|mypy\.ini$)' && echo "run-tests=true" >> $GITHUB_OUTPUT || true fi # Check if we should run hypothesis tests GIT_BRANCH=${GITHUB_BASE_REF:-${GITHUB_REF#refs/heads/}} echo $GIT_BRANCH if $(echo "$GIT_BRANCH" | grep -q -w '3\.\(8\|9\|10\|11\)'); then echo "Branch too old for hypothesis tests" echo "run-hypothesis=false" >> $GITHUB_OUTPUT else echo "Run hypothesis tests" echo "run-hypothesis=true" >> $GITHUB_OUTPUT fi # oss-fuzz maintains a configuration for fuzzing the main branch of # CPython, so CIFuzz should be run only for code that is likely to be # merged into the main branch; compatibility with older branches may # be broken. FUZZ_RELEVANT_FILES='(\.c$|\.h$|\.cpp$|^configure$|^\.github/workflows/build\.yml$|^Modules/_xxtestfuzz)' if [ "$GITHUB_BASE_REF" = "main" ] && [ "$(git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qE $FUZZ_RELEVANT_FILES; echo $?)" -eq 0 ]; then # The tests are pretty slow so they are executed only for PRs # changing relevant files. echo "Run CIFuzz tests" echo "run-cifuzz=true" >> $GITHUB_OUTPUT else echo "Branch too old for CIFuzz tests; or no C files were changed" echo "run-cifuzz=false" >> $GITHUB_OUTPUT fi - name: Compute hash for config cache key id: config-hash run: | echo "hash=${{ hashFiles('configure', 'configure.ac', '.github/workflows/build.yml') }}" >> $GITHUB_OUTPUT - name: Get a list of the changed documentation-related files if: github.event_name == 'pull_request' id: changed-docs-files uses: Ana06/get-changed-files@v2.3.0 with: filter: | Doc/** Misc/** .github/workflows/reusable-docs.yml format: csv # works for paths with spaces - name: Check for docs changes # We only want to run this on PRs when related files are changed, # or when user triggers manual workflow run. if: >- ( github.event_name == 'pull_request' && steps.changed-docs-files.outputs.added_modified_renamed != '' ) || github.event_name == 'workflow_dispatch' id: docs-changes run: | echo "run-docs=true" >> "${GITHUB_OUTPUT}" - name: Get a list of the MSI installer-related files if: github.event_name == 'pull_request' id: changed-win-msi-files uses: Ana06/get-changed-files@v2.3.0 with: filter: | Tools/msi/** .github/workflows/reusable-windows-msi.yml format: csv # works for paths with spaces - name: Check for changes in MSI installer-related files # We only want to run this on PRs when related files are changed, # or when user triggers manual workflow run. if: >- ( github.event_name == 'pull_request' && steps.changed-win-msi-files.outputs.added_modified_renamed != '' ) || github.event_name == 'workflow_dispatch' id: win-msi-changes run: | echo "run-win-msi=true" >> "${GITHUB_OUTPUT}"