diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b9b412efc..aac875584 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ name: Continuous integration checks -run-name: CI checks for ${{github.event_name}} by ${{github.actor}} +run-name: Continuous integration checks triggered by ${{github.event_name}} on: pull_request: @@ -23,6 +23,11 @@ on: # Allow manual invocation. workflow_dispatch: inputs: + sha: + description: 'SHA of commit to run against:' + type: string + required: true + python_ver: description: Normal version of Python to use type: string @@ -38,7 +43,7 @@ concurrency: env: # Default Python version to use. - python_ver: "3.10.11" + python_ver: "3.12" # Oldest Python version to use, for max_compat tests. python_compat_ver: "3.10" @@ -54,14 +59,61 @@ env: dev_tools/requirements/max_compat/pytest-max-compat.env.txt jobs: - Setup: - runs-on: ubuntu-latest - timeout-minutes: 10 + Changes: + runs-on: ubuntu-24.04 + timeout-minutes: 5 + outputs: + python: ${{steps.filter.outputs.python}} + python_files: ${{steps.filter.outputs.python_files}} steps: + # When invoked manually, use the given SHA to figure out the change list. + - if: github.event_name == 'workflow_dispatch' + name: Use the user-provided SHA as the basis for comparison + env: + GH_TOKEN: ${{github.token}} + run: | + set -x +e + url="repos/${{github.repository}}/commits/${{inputs.sha}}" + full_sha="$(gh api $url -q '.sha')" + exit_code=$? + if [[ "$exit_code" == "0" ]]; then + echo "base=$full_sha" >> "$GITHUB_ENV" + else + { + echo "### :x: Workflow error" + echo "The SHA provided to _Run Workflow_ does not exist:" + echo "${{inputs.sha}}" + } >> "$GITHUB_STEP_SUMMARY" + exit 1 + fi + + - if: github.event_name != 'workflow_dispatch' + name: Use ref ${{github.ref_name}} as the basis for comparison + run: | + echo base=${{github.ref_name}} >> "$GITHUB_ENV" + - name: Check out a copy of the OpenFermion git repository uses: actions/checkout@v4 + + - name: Determine files changed by this ${{github.event_name}} event + uses: dorny/paths-filter@v3 + id: filter with: - fetch-depth: 0 + base: ${{env.base}} + list-files: 'shell' + # The outputs will be variables named "foo_files" for a filter "foo". + filters: | + python: + - added|modified: + - '**/*.py' + + Setup: + if: needs.Changes.outputs.python == 'true' + needs: Changes + runs-on: ubuntu-latest + steps: + - name: Check out a copy of the git repository + uses: actions/checkout@v4 - name: Set up Python with caching of pip dependencies uses: actions/setup-python@v5 @@ -82,17 +134,19 @@ jobs: pip list echo "::endgroup::" - format: - name: Format check - needs: Setup + Python-format: + if: needs.Changes.outputs.python == 'true' + name: Python format checks + needs: [Changes, Setup] runs-on: ubuntu-latest - timeout-minutes: 10 steps: - - uses: actions/checkout@v4 + - name: Check out a copy of the git repository + uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: actions/setup-python@v5 + - name: Set up Python and restore cache + uses: actions/setup-python@v5 with: python-version: ${{inputs.python_ver || env.python_ver}} architecture: "x64" @@ -105,15 +159,17 @@ jobs: - name: Format run: check/format-incremental - mypy: - name: Type check - needs: Setup + Python-mypy: + if: needs.Changes.outputs.python == 'true' + name: Python type checks + needs: [Changes, Setup] runs-on: ubuntu-latest - timeout-minutes: 10 steps: - - uses: actions/checkout@v4 + - name: Check out a copy of the git repository + uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - name: Set up Python and restore cache + uses: actions/setup-python@v5 with: python-version: ${{inputs.python_ver || env.python_ver}} architecture: "x64" @@ -126,15 +182,17 @@ jobs: - name: Type check run: check/mypy - pylint: - name: Lint check - needs: Setup + Python-lint: + if: needs.Changes.outputs.python == 'true' + name: Python lint checks + needs: [Changes, Setup] runs-on: ubuntu-latest - timeout-minutes: 10 steps: - - uses: actions/checkout@v4 + - name: Check out a copy of the git repository + uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - name: Set up Python and restore cache + uses: actions/setup-python@v5 with: python-version: ${{inputs.python_ver || env.python_ver}} architecture: "x64" @@ -147,41 +205,29 @@ jobs: - name: Lint run: check/pylint - pytest-max-compat: - name: Pytest max compat - runs-on: ubuntu-20.04 - timeout-minutes: 15 - steps: - - uses: actions/checkout@v4 - - # Note: deliberately not using our Python cache here b/c this runs - # a different version of Python. - - uses: actions/setup-python@v5 - with: - python-version: ${{env.python_compat_ver}} + # The next set of matrix tests each consist of 2 job definitions. The job + # named "Thing-matrix" define a matrix of runs for different platforms. It's + # set with "fail-fast: false" so that a failure in one of matrix jobs doesn't + # cause this entire CI workflow to abort. Then, the job named "Thing" is the + # one that actually reports the results. It needs to be an independent job it + # has to test the results of all the matrix runs. - - name: Install requirements - run: | - pip install -r dev_tools/requirements/max_compat/pytest-max-compat.env.txt - - - name: Pytest check - run: check/pytest - shell: bash - - pytest-matrix: + Pytest-matrix: + if: needs.Changes.outputs.python == 'true' name: Pytest matrix - needs: Setup + needs: [Changes, Setup] runs-on: ${{ matrix.os }} - timeout-minutes: 15 strategy: matrix: os: [ ubuntu-latest, macos-latest, windows-latest ] cirq-version: [ 1.4.1 ] fail-fast: false steps: - - uses: actions/checkout@v4 + - name: Check out a copy of the git repository + uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - name: Set up Python and restore cache + uses: actions/setup-python@v5 with: python-version: ${{inputs.python_ver || env.python_ver}} cache: pip @@ -196,10 +242,10 @@ jobs: run: check/pytest shell: bash - pytest: - if: always() + Pytest: + if: needs.Changes.outputs.python == 'true' && (success() || failure()) name: Pytest - needs: pytest-matrix + needs: [Changes, Pytest-matrix] runs-on: ubuntu-latest steps: - run: | @@ -210,20 +256,22 @@ jobs: exit 1 fi - pytest-extra-matrix: + Pytest-extra-matrix: + if: needs.Changes.outputs.python == 'true' name: Pytest extra matrix - needs: Setup + needs: [Changes, Setup] runs-on: ${{ matrix.os }} - timeout-minutes: 15 strategy: matrix: os: [ubuntu-latest, macos-latest] cirq-version: [ 1.4.1 ] fail-fast: false steps: - - uses: actions/checkout@v4 + - name: Check out a copy of the git repository + uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - name: Set up Python and restore cache + uses: actions/setup-python@v5 with: python-version: ${{inputs.python_ver || env.python_ver}} cache: pip @@ -238,10 +286,10 @@ jobs: run: check/pytest -m "not slow" src/openfermion/resource_estimates shell: bash - pytest-extra: - if: always() + Pytest-extra: + if: needs.Changes.outputs.python == 'true' && (success() || failure()) name: Pytest extra - needs: pytest-extra-matrix + needs: [Changes, Pytest-extra-matrix] runs-on: ubuntu-latest steps: - run: | @@ -252,16 +300,43 @@ jobs: exit 1 fi - coverage: - name: Coverage check - needs: Setup + Pytest-max-compat: + if: needs.Changes.outputs.python == 'true' + name: Pytest max compatibility + needs: [Changes, Setup] + runs-on: ubuntu-20.04 + steps: + - name: Check out a copy of the git repository + uses: actions/checkout@v4 + + # Note: deliberately not using our Python cache here b/c this runs + # a different version of Python. + - name: Set up Python and restore cache + uses: actions/setup-python@v5 + with: + python-version: ${{env.python_compat_ver}} + + - name: Install requirements + run: | + pip install -r dev_tools/requirements/max_compat/pytest-max-compat.env.txt + + - name: Pytest check + run: check/pytest + shell: bash + + Coverage: + if: needs.Changes.outputs.python == 'true' + name: Code coverage checks + needs: [Changes, Setup] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - name: Check out a copy of the git repository + uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: actions/setup-python@v5 + - name: Set up Python and restore cache + uses: actions/setup-python@v5 with: python-version: ${{inputs.python_ver || env.python_ver}} cache: pip