From b89e4e4cc443f4c998caf8ffa31623c5616da825 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 24 Oct 2022 20:53:52 +0200 Subject: [PATCH 1/2] Implement opt-in change detection in pull requests This patch introduces a `pull-request-change-detection` action input that allows the end-users to request running `ansible-test` in change detection mode. It is only supported in for pull requests at the moment because `ansible-test` does not currently know how to interact with the environment variables that GitHub Actions CI/CD workflows set [1]. With this feature, the users will be able to save some of the CI compute time due to `ansible-test` skipping the tests that are not affected by the changes in PRs. [1] https://github.com/ansible-community/ansible-test-gh-action/pull/49/files#r1023412786 --- README.md | 12 ++++++++ action.yml | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4393d49..5c4b5f6 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,18 @@ version supported by the given `ansible-core-version` **(DEFAULT: `auto`)** Extra command to invoke before ansible-test **(OPTIONAL)** +### `pull-request-change-detection` + +Whether to use change detection for pull requests. If set to `true`, will +use change detection to determine changed files against the target branch, +and will not upload code coverage results. If the invocation is not from a +pull request, this option is ignored. Note that this requires +`collection-src-directory` to be empty, or it has to be a git repository +checkout where `collection-src-directory`/`collection-root` ends with +`ansible_collections/{namespace}/{name}`, or it has to be a git +repository checkout where `collection-root` is `.`. **(DEFAULT: `false`)** + + ### `python-version` **(DEPRECATED)** Use `origin-python-version` instead. diff --git a/action.yml b/action.yml index bf7a577..e99957d 100644 --- a/action.yml +++ b/action.yml @@ -45,6 +45,17 @@ inputs: default: auto pre-test-cmd: description: Extra command to invoke before ansible-test + pull-request-change-detection: + description: >- + Whether to use change detection for pull requests. If set to `true`, will + use change detection to determine changed files against the target + branch, and will not upload code coverage results. If the invocation is + not from a pull request, this option is ignored. Note that this requires + `collection-src-directory` to be empty, or it has to be a git repository + checkout where `collection-src-directory`/`collection-root` ends with + `ansible_collections/{namespace}/{name}`, or it has to be a git + repository checkout where `collection-root` is `.`. + default: 'false' python-version: description: >- **(DEPRECATED)** Use `origin-python-version` instead. This is only kept @@ -191,6 +202,45 @@ runs: set +x shell: bash + - name: Log the next step action + run: echo ▷ Figuring out ansible-test flags + shell: bash + - name: Determine ansible-test flags + id: ansible-test-flags + run: | + # Compute whether to use change detection and coverage + import json + import os + import pathlib + import sys + + FILE_APPEND_MODE = 'a' + OUTPUTS_FILE_PATH = pathlib.Path(os.environ['GITHUB_OUTPUT']) + + def set_output(name, value): + with OUTPUTS_FILE_PATH.open(FILE_APPEND_MODE) as outputs_file: + outputs_file.writelines(f'{name}={value}{os.linesep}') + + # Input from GHA + pull_request_change_detection = json.loads('${{ + inputs.pull-request-change-detection + }}') + pull_request_branch = '${{ github.event.pull_request.base.ref || '' }}' + + # Compute coverage and change detection arguments + coverage_arg = '--coverage' + change_detection_arg = '' + if pull_request_branch and pull_request_change_detection: + coverage_arg = '' + change_detection_arg = ( + f'--changed --base-branch {pull_request_branch}' + ) + + # Set computed coverage-arg and change-detection-arg + set_output('coverage-arg', coverage_arg) + set_output('change-detection-arg', change_detection_arg) + shell: python + - name: Log the next step action if: >- !inputs.collection-src-directory @@ -205,6 +255,39 @@ runs: path: .tmp-ansible-collection-checkout persist-credentials: false ref: ${{ inputs.git-checkout-ref }} + fetch-depth: >- + ${{ + steps.ansible-test-flags.outputs.change-detection-arg + && '0' || '1' + }} + + - name: Log the next step action + if: >- + !inputs.collection-src-directory + && steps.ansible-test-flags.outputs.change-detection-arg + run: >- + echo ▷ Create branches for change detection + shell: bash + - name: Create branches for change detection + if: >- + !inputs.collection-src-directory + && steps.ansible-test-flags.outputs.change-detection-arg + run: | + # Create a branch for the current HEAD, which happens to be a merge commit + git checkout -b 'pull-request-${{ github.event.pull_request.number }}' + + # Name the target branch + git branch '${{ + github.event.pull_request.base.ref + }}' --track 'origin/${{ + github.event.pull_request.base.ref + }}' + + # Show branch information + git branch -vv + shell: bash + working-directory: >- + .tmp-ansible-collection-checkout - name: Log the next step action run: >- @@ -376,7 +459,8 @@ runs: ; ~/.local/bin/ansible-test ${{ inputs.testing-type }} -v --color - --coverage + ${{ steps.ansible-test-flags.outputs.coverage-arg }} + ${{ steps.ansible-test-flags.outputs.change-detection-arg }} ${{ inputs.testing-type == 'sanity' && '--junit' @@ -426,10 +510,12 @@ runs: working-directory: ${{ steps.collection-metadata.outputs.checkout-path }} - name: Log the next step action + if: steps.ansible-test-flags.outputs.coverage-arg != '' run: >- echo ▷ Generating a coverage report... shell: bash - name: Generate coverage report + if: steps.ansible-test-flags.outputs.coverage-arg != '' run: >- set -x ; @@ -443,6 +529,7 @@ runs: working-directory: ${{ steps.collection-metadata.outputs.checkout-path }} - name: Log the next step action + if: steps.ansible-test-flags.outputs.coverage-arg != '' run: >- echo ▷ Sending the coverage data over to https://codecov.io/gh/${{ github.repository }}... @@ -450,6 +537,7 @@ runs: - name: >- Send the coverage data over to https://codecov.io/gh/${{ github.repository }} + if: steps.ansible-test-flags.outputs.coverage-arg != '' uses: codecov/codecov-action@v3 with: files: >- From 5257e71fda07605920bc84223e81418899461cab Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 9 Nov 2022 07:57:26 +0100 Subject: [PATCH 2/2] Add smoke/integration tests for change detection --- .github/workflows/test-action.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-action.yml b/.github/workflows/test-action.yml index a4aa5f5..2bfc100 100644 --- a/.github/workflows/test-action.yml +++ b/.github/workflows/test-action.yml @@ -36,6 +36,8 @@ jobs: - '' pre-test-cmd: - '' + pull-request-change-detection: + - '' target: - '' target-python-version: @@ -68,8 +70,10 @@ jobs: testing-type: units - ansible-core-version: stable-2.13 collection-root: .internal/ansible/ansible_collections/internal/test - collection-src-directory: ./.tmp-action-checkout + # NOTE: A missing `collection-src-directory` input causes + # NOTE: fetching the repo from GitHub. origin-python-version: '3.9' + pull-request-change-detection: 'true' testing-type: integration - ansible-core-version: stable-2.13 collection-root: .internal/ansible/ansible_collections/internal/test @@ -111,6 +115,8 @@ jobs: git-checkout-ref: ${{ matrix.git-checkout-ref }} origin-python-version: ${{ matrix.origin-python-version }} pre-test-cmd: ${{ matrix.pre-test-cmd }} + pull-request-change-detection: >- + ${{ matrix.pull-request-change-detection || 'false' }} target: ${{ matrix.target }} target-python-version: ${{ matrix.target-python-version }} testing-type: ${{ matrix.testing-type }}