Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CI: Add a verify-success reusable workflow to use for required checks #3320

Merged
merged 7 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,11 @@ jobs:
- name: Print installed versions
if: always()
run: .github/workflows/print_versions.sh
pytest-success:
name: pytest Result
needs:
- pytest
if: ${{ always() }}
uses: ./.github/workflows/verify-success.yml
with:
needs_context: ${{ toJson(needs) }}
30 changes: 20 additions & 10 deletions .github/workflows/python-code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@

jobs:
python-checks:
name: Python Code Quality
name: Python Code Quality Checks

concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}-${{
matrix.pylint-version }}
group: ${{ github.workflow }}-${{ github.job }}-${{
github.event_name == 'pull_request' &&
github.head_ref || github.sha }}-${{ matrix.pylint-version }}
cancel-in-progress: true

# Using matrix just to get variables which are not environmental variables
Expand All @@ -26,11 +27,11 @@
matrix:
include:
- os: ubuntu-22.04
python-version: '3.10'
min-python-version: '3.7'
black-version: '23.1.0'
flake8-version: '3.9.2'
pylint-version: '2.12.2'
python-version: "3.10"
min-python-version: "3.7"
black-version: "23.1.0"
flake8-version: "3.9.2"
pylint-version: "2.12.2"

runs-on: ${{ matrix.os }}

Expand All @@ -39,7 +40,7 @@
run: |
echo OS: ${{ matrix.os }}
echo Python: ${{ matrix.python-version }}
echo Minimimal Python version: ${{ matrix.min-python-version }}
echo Minimal Python version: ${{ matrix.min-python-version }}
echo Black: ${{ matrix.black-version }}
echo Flake8: ${{ matrix.flake8-version }}
echo Pylint: ${{ matrix.pylint-version }}
Expand All @@ -50,13 +51,14 @@
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: pip
echoix marked this conversation as resolved.
Show resolved Hide resolved

- name: Install non-Python dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y wget git gawk findutils
xargs -a <(awk '! /^ *(#|$)/' ".github/workflows/apt.txt") -r -- \
sudo apt-get install -y --no-install-recommends --no-install-suggests
sudo apt-get install -y --no-install-recommends --no-install-suggests

- name: Install Python dependencies
run: |
Expand Down Expand Up @@ -111,7 +113,7 @@
cd gui/wxpython
pylint --persistent=no --py-version=${{ matrix.min-python-version }} --jobs=$(nproc) *

- name: Run Pylint on other files using pytest

Check warning on line 116 in .github/workflows/python-code-quality.yml

View workflow job for this annotation

GitHub Actions / Python Code Quality Checks (ubuntu-22.04, 3.10, 3.7, 23.1.0, 3.9.2, 2.12.2)

Temporarily downgraded pytest-pylint to allow merging other PRs. The errors reported with a newer version seem legitimite and should be fixed (2023-10-18, see https://github.com/OSGeo/grass/pull/3205)
run: |
pip install pytest pytest-pylint==0.19
echo "::warning file=.github/workflows/python-code-quality.yml,line=116,col=42,endColumn=48::\
Expand Down Expand Up @@ -146,3 +148,11 @@
name: sphinx-grass
path: sphinx-grass
retention-days: 3
python-success:
name: Python Code Quality Result
wenzeslaus marked this conversation as resolved.
Show resolved Hide resolved
needs:
- python-checks
if: ${{ always() }}
uses: ./.github/workflows/verify-success.yml
with:
needs_context: ${{ toJson(needs) }}
12 changes: 10 additions & 2 deletions .github/workflows/ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ on:
- releasebranch_*

jobs:
build-and-test:
ubuntu:
name: ${{ matrix.name }} tests

concurrency:
Expand All @@ -26,7 +26,7 @@ jobs:
strategy:
matrix:
include:
- name: '22.04'
- name: "22.04"
os: ubuntu-22.04
config: ubuntu-22.04
# This is without optional things but it still keeps things useful,
Expand Down Expand Up @@ -95,3 +95,11 @@ jobs:
- name: Print installed versions
if: always()
run: .github/workflows/print_versions.sh
build-and-test-success:
name: Build & Test Result
wenzeslaus marked this conversation as resolved.
Show resolved Hide resolved
needs:
- ubuntu
if: ${{ always() }}
uses: ./.github/workflows/verify-success.yml
with:
needs_context: ${{ toJson(needs) }}
155 changes: 155 additions & 0 deletions .github/workflows/verify-success.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
---
name: Verify Success reusable workflow

# Use this reusable workflow as a job of workflow to check that
# all jobs, including ones ran through a matrix, were successful.
# This job can then be used as a required status check in the
# repo's rulesets, that allows to change the required jobs or
# the matrix values of a required job without needing to change
# the rulesets settings. In the future, GitHub might have a
# solution to this natively.

# This reusable workflow has inputs to change what is required
# to have this workflow pass. It handles the cases were there were
# skipped jobs, and no successful jobs.

# The jobs to check must set as the `needs` for the job calling this
# reusable workflow. This also means that the job ids should be in the
# same workflow file. The calling job must be set to always run to be
# triggered when jobs are skipped or cancelled.
# Then, set the `needs_context` input like:
# `needs_context: ${{ toJson(needs) }}`

# Example usage, as a job inside a workflow:
# ```
# jobs:
# a-job-id:
# ...
# another-job-id:
# ...
# some-job-success:
# name: Some Job Result
# needs:
# - a-job-id
# - another-job-id
# if: ${{ always() }}
# uses: ./.github/workflows/verify-success.yml
# with:
# needs_context: ${{ toJson(needs) }}
# ```

on:
workflow_call:
inputs:
needs_context:
type: string
required: true
# Can't escape the handlebars in the description
description:
In the calling job that defines all the needed jobs,
send `toJson(needs)` inside `$` followed by `{{ }}`
fail_if_failure:
type: boolean
default: true
description:
If true, this workflow will fail if any job from 'needs_context was
failed
fail_if_cancelled:
type: boolean
default: true
description:
If true, this workflow will fail if any job from 'needs_context' was
cancelled
fail_if_skipped:
type: boolean
default: false
description:
If true, this workflow will fail if any job from 'needs_context' was
skipped
require_success:
type: boolean
default: true
description:
If true, this workflow will fail if no job from 'needs_context' was
successful

jobs:
verify-success:
name: Success
wenzeslaus marked this conversation as resolved.
Show resolved Hide resolved
runs-on: ubuntu-latest
continue-on-error: true
steps:
- name: Set outputs for each job result type
id: has-result
run: |
echo "failure=${{
contains(env.NEEDS_RESULT, 'failure') }}" >> "$GITHUB_OUTPUT"
echo "cancelled=${{
contains(env.NEEDS_RESULT, 'cancelled') }}" >> "$GITHUB_OUTPUT"
echo "skipped=${{
contains(env.NEEDS_RESULT, 'skipped') }}" >> "$GITHUB_OUTPUT"
echo "success=${{
contains(env.NEEDS_RESULT, 'success') }}" >> "$GITHUB_OUTPUT"
env:
NEEDS_RESULT: ${{ toJson(fromJson(inputs.needs_context).*.result) }}
- name: Set exit codes for each job result type
id: exit-code
run: |
echo "failure=${{ inputs.fail_if_failure &&
fromJson(steps.has-result.outputs.failure) && 1 || 0
}}" >> "$GITHUB_OUTPUT"
echo "cancelled=${{ inputs.fail_if_cancelled &&
fromJson(steps.has-result.outputs.cancelled) && 1 || 0
}}" >> "$GITHUB_OUTPUT"
echo "skipped=${{ inputs.fail_if_skipped &&
fromJson(steps.has-result.outputs.skipped) && 1 || 0
}}" >> "$GITHUB_OUTPUT"
echo "success=${{ inputs.require_success &&
!fromJson(steps.has-result.outputs.success) && 1 || 0
}}" >> "$GITHUB_OUTPUT"
- name: Set messages for each job result type
id: message
run: |
echo "failure=${{ format('{0}{1} were failed',
(steps.exit-code.outputs.failure == 1) && env.P1 || env.P2,
(steps.has-result.outputs.failure == 'true') && env.M1 || env.M2)
}}" >> "$GITHUB_OUTPUT"
echo "cancelled=${{ format('{0}{1} were cancelled',
(steps.exit-code.outputs.cancelled == 1) && env.P1 || env.P2,
(steps.has-result.outputs.cancelled == 'true') && env.M1 || env.M2)
}}" >> "$GITHUB_OUTPUT"
echo "skipped=${{ format('{0}{1} were skipped',
(steps.exit-code.outputs.skipped == 1) && env.P1 || env.P2,
(steps.has-result.outputs.skipped == 'true') && env.M1 || env.M2)
}}" >> "$GITHUB_OUTPUT"
echo "success=${{ format('{0}{1} were successful',
(steps.exit-code.outputs.success == 1) && env.P1 || env.P2,
(steps.has-result.outputs.success == 'true') && env.M1 || env.M2)
}}" >> "$GITHUB_OUTPUT"
env:
P1: "::error ::" # Common message prefix if step will fail
P2: "" # Common message prefix if step will not fail
M1: "Some jobs" # Common message if result is true
M2: "No jobs" # Common message if result is false

- name: Check for failed jobs
run: |
echo "${{ steps.message.outputs.failure }}"
exit ${{ steps.exit-code.outputs.failure }}
- name: Check for cancelled jobs
run: |
echo "${{ steps.message.outputs.cancelled }}"
exit ${{ steps.exit-code.outputs.cancelled }}
- name: Check for skipped jobs
run: |
echo "${{ steps.message.outputs.skipped }}"
exit ${{ steps.exit-code.outputs.skipped }}
- name: Check for successful jobs
run: |
echo "${{ steps.message.outputs.success }}"
exit ${{ steps.exit-code.outputs.success }}

- run: echo "Checks passed successfully"
if: ${{ success() }}
- run: echo "Checks failed"
if: ${{ !success() }}
Loading