Skip to content

Commit

Permalink
Merge a1e739e into 11f28e0
Browse files Browse the repository at this point in the history
  • Loading branch information
CasperWA authored Oct 30, 2023
2 parents 11f28e0 + a1e739e commit ce8691d
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 13 deletions.
31 changes: 31 additions & 0 deletions .github/workflows/ci_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,17 @@ jobs:
token: '${{ secrets.CI_PUSH_TO_PROTECTED_BRANCH }}'
branch: protected
unprotect_reviews: true
acceptable_conclusions: success,skipped
debug: true

- name: Pushing to a protected branch without any changes
uses: ./
with:
token: '${{ secrets.CI_PUSH_TO_PROTECTED_BRANCH }}'
ref: refs/heads/protected
unprotect_reviews: true
acceptable_conclusions: success,skipped
debug: true

force-pushing:
needs: [protected]
Expand Down Expand Up @@ -138,6 +142,7 @@ jobs:
token: '${{ secrets.CI_PUSH_TO_PROTECTED_BRANCH }}'
branch: protected
unprotect_reviews: true
acceptable_conclusions: success,skipped

- name: This runs ONLY if the previous step doesn't fail
if: steps.push_no_force.outcome != 'failure' || steps.push_no_force.conclusion != 'success'
Expand All @@ -152,6 +157,7 @@ jobs:
branch: protected
unprotect_reviews: true
force: yes
acceptable_conclusions: success,skipped

branch_and_ref:
needs: [force-pushing]
Expand Down Expand Up @@ -220,6 +226,31 @@ jobs:
force: yes
debug: true

acceptable_conclusions:
needs: [path]
runs-on: ubuntu-latest
name: Testing - Default for `acceptable_conclusions` with skipped checks
steps:
- name: Use local action (checkout)
uses: actions/checkout@v4

- name: Push to protected branch without 'skipped' in 'acceptable_conclusions'
id: push_skipped
continue-on-error: true
uses: ./
with:
token: '${{ secrets.CI_PUSH_TO_PROTECTED_BRANCH }}'
branch: protected
unprotect_reviews: true
# Default value - set here explicitly for clarity
acceptable_conclusions: success

- name: This runs ONLY if the previous step doesn't fail
if: steps.push_skipped.outcome != 'failure' || steps.push_skipped.conclusion != 'success'
run: |
echo "Outcome: ${{ steps.push_skipped.outcome }} (not 'failure'), Conclusion: ${{ steps.push_skipped.conclusion }} (not 'success')"
exit 1
pre-commit:
runs-on: ubuntu-latest
steps:
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/test_status_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,11 @@ jobs:
steps:
- name: Important status check
run: echo "Very important status check - SUCCESS!"

skipped_mock_status_check:
runs-on: ubuntu-latest
name: Skipped Mock Status Check
if: ! always()
steps:
- name: Skipped status check
run: echo "Very important skipped status check - SKIPPED!"
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ All input names in **bold** are _required_.
| `unprotect_reviews` | Momentarily remove pull request review protection from target branch.<br>**Note**: One needs administrative access to the repository to be able to use this feature. This means two things need to match up: The PAT must represent a user with administrative rights, and these rights need to be granted to the usage scope of the PAT. | `False` |
| `debug` | Set `set -x` in `entrypoint.sh` when running the action. This is for debugging the action. | `False` |
| `path` | A path to the working directory of the action. This should be relative to the `$GITHUB_WORKSPACE`. | `.` |
| `acceptable_conclusions` | A comma-separated list of acceptable statuses. If any of these statuses are present, the action will not fail.</br></br>See the [GitHub REST API documentation](https://docs.github.com/en/rest/actions/workflow-jobs#get-a-job-for-a-workflow-run), specifically, the Response schema's "conclusion" property's `enum` values, for a complete list of supported values (excluding `null`). | `success` |

## License

Expand Down
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ inputs:
description: 'A path to the working directory of the action. This should be relative to the $GITHUB_WORKSPACE.'
required: false
default: '.'
acceptable_conclusions:
description: 'A comma-separated list of acceptable conclusions. If any of these conclusions are present, the action will not fail.'
required: false
default: 'success'
runs:
using: 'docker'
image: 'Dockerfile'
44 changes: 40 additions & 4 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ unprotect () {
y | Y | yes | Yes | YES | true | True | TRUE | on | On | ON)
if [ -n "${PUSH_PROTECTED_CHANGED_BRANCH}" ] && [ -n "${PUSH_PROTECTED_PROTECTED_BRANCH}" ]; then
echo -e "\nRemove '${INPUT_BRANCH}' pull request review protection ..."
push-action --token "${INPUT_TOKEN}" --ref "${INPUT_BRANCH}" --temp-branch "${PUSH_PROTECTED_TEMPORARY_BRANCH}" -- unprotect_reviews

push-action \
--token "${INPUT_TOKEN}" \
--ref "${INPUT_BRANCH}" \
--temp-branch "${PUSH_PROTECTED_TEMPORARY_BRANCH}" \
-- unprotect_reviews

echo "Remove '${INPUT_BRANCH}' pull request review protection ... DONE!"
fi
;;
Expand All @@ -33,7 +39,13 @@ protect () {
y | Y | yes | Yes | YES | true | True | TRUE | on | On | ON)
if [ -n "${PUSH_PROTECTED_CHANGED_BRANCH}" ] && [ -n "${PUSH_PROTECTED_PROTECTED_BRANCH}" ]; then
echo -e "\nRe-add '${INPUT_BRANCH}' pull request review protection ..."
push-action --token "${INPUT_TOKEN}" --ref "${INPUT_BRANCH}" --temp-branch "${PUSH_PROTECTED_TEMPORARY_BRANCH}" -- protect_reviews

push-action \
--token "${INPUT_TOKEN}" \
--ref "${INPUT_BRANCH}" \
--temp-branch "${PUSH_PROTECTED_TEMPORARY_BRANCH}" \
-- protect_reviews

echo "Re-add '${INPUT_BRANCH}' pull request review protection ... DONE!"
fi
;;
Expand All @@ -49,14 +61,38 @@ wait_for_checks() {
echo -e "\nWaiting for status checks to finish for '${PUSH_PROTECTED_TEMPORARY_BRANCH}' ..."
# Sleep for 5 seconds to let the workflows start
sleep ${INPUT_SLEEP}
push-action --token "${INPUT_TOKEN}" --ref "${INPUT_BRANCH}" --temp-branch "${PUSH_PROTECTED_TEMPORARY_BRANCH}" --wait-timeout "${INPUT_TIMEOUT}" --wait-interval "${INPUT_INTERVAL}" -- wait_for_checks

ACCEPTABLE_CONCLUSIONS=()
if [ -n "${INPUT_ACCEPTABLE_CONCLUSIONS}" ]; then
while IFS="," read -ra CONCLUSIONS; do
for CONCLUSION in "${CONCLUSIONS[@]}"; do
ACCEPTABLE_CONCLUSIONS+=(--acceptable-conclusion="${CONCLUSION}")
done
done <<< "${INPUT_ACCEPTABLE_CONCLUSIONS}"
fi

push-action \
--token "${INPUT_TOKEN}" \
--ref "${INPUT_BRANCH}" \
--temp-branch "${PUSH_PROTECTED_TEMPORARY_BRANCH}" \
--wait-timeout "${INPUT_TIMEOUT}" \
--wait-interval "${INPUT_INTERVAL}"\
"${ACCEPTABLE_CONCLUSIONS[@]}" \
-- wait_for_checks

echo "Waiting for status checks to finish for '${PUSH_PROTECTED_TEMPORARY_BRANCH}' ... DONE!"
fi
}
remove_remote_temp_branch() {
if [ -n "${PUSH_PROTECTED_CHANGED_BRANCH}" ] && [ -n "${PUSH_PROTECTED_PROTECTED_BRANCH}" ]; then
echo -e "\nRemoving temporary branch '${PUSH_PROTECTED_TEMPORARY_BRANCH}' ..."
push-action --token "${INPUT_TOKEN}" --ref "${INPUT_BRANCH}" --temp-branch "${PUSH_PROTECTED_TEMPORARY_BRANCH}" -- remove_temp_branch

push-action \
--token "${INPUT_TOKEN}" \
--ref "${INPUT_BRANCH}" \
--temp-branch "${PUSH_PROTECTED_TEMPORARY_BRANCH}" \
-- remove_temp_branch

echo "Removing temporary branch '${PUSH_PROTECTED_TEMPORARY_BRANCH}' ... DONE!"
fi
}
Expand Down
34 changes: 26 additions & 8 deletions push_action/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
Match found required GitHub Actions runs found in 1)
4) Wait and do 3) again until required GitHub Actions jobs have "status": "completed"
If "conclusion": "success" YAY
If "conclusion" != "success" FAIL this action
If "conclusion" in inputs provided through `--acceptable-conclusion`
(default: "success") YAY
Otherwise, FAIL this action
"""
import argparse
Expand All @@ -39,8 +40,9 @@
get_workflow_run_jobs,
remove_branch,
)
from push_action.validate import validate_conclusions

if TYPE_CHECKING:
if TYPE_CHECKING: # pragma: no cover
from typing import Any, Dict


Expand Down Expand Up @@ -75,7 +77,10 @@ def wait() -> None:
# All jobs are completed
print("All required GitHub Actions jobs complete!", flush=True)
unsuccessful_jobs = [
_ for _ in actions_required if _.get("conclusion", "") != "success"
job_run
for job_run in actions_required
if job_run.get("conclusion", "")
not in IN_MEMORY_CACHE["acceptable_conclusions"]
]
break

Expand All @@ -95,6 +100,7 @@ def wait() -> None:
if _["name"] in required_statuses and _["status"] != "completed"
]
)

if actions_required:
print(
f"{len(actions_required)} required GitHub Actions jobs have not yet "
Expand Down Expand Up @@ -237,6 +243,16 @@ def main() -> None:
),
default=30,
)
parser.add_argument(
"--acceptable-conclusion",
type=str,
help=(
"Acceptable conclusion for the wait_for_checks run to be considered "
"successful"
),
action="append",
default=["success"],
)
parser.add_argument(
"ACTION",
type=str,
Expand All @@ -254,6 +270,10 @@ def main() -> None:

fail = ""
try:
IN_MEMORY_CACHE["acceptable_conclusions"] = validate_conclusions(
IN_MEMORY_CACHE["args"].acceptable_conclusion
)

if IN_MEMORY_CACHE["args"].ACTION == "wait_for_checks":
wait()
elif IN_MEMORY_CACHE["args"].ACTION == "remove_temp_branch":
Expand All @@ -266,10 +286,8 @@ def main() -> None:
print(protected_branch(IN_MEMORY_CACHE["args"].ref), end="", flush=True)
else:
raise RuntimeError(f"Unknown ACTIONS {IN_MEMORY_CACHE['args'].ACTION!r}")

except Exception as exc: # pylint: disable=broad-except
fail = f"{exc.__class__.__name__}: {exc}"

if fail:
sys.exit(fail)
else:
sys.exit()
sys.exit(fail or None)
2 changes: 1 addition & 1 deletion push_action/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from push_action.cache import IN_MEMORY_CACHE

if TYPE_CHECKING:
from typing import Callable, List, Optional, Union
from typing import Callable, List, Union


REQUEST_TIMEOUT = 10 # in seconds
Expand Down
42 changes: 42 additions & 0 deletions push_action/validate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""Validate inputs."""
from __future__ import annotations


VALID_CONCLUSIONS = [
"action_required",
"cancelled",
"failure",
"neutral",
"skipped",
"success",
"timed_out",
]
"""List of valid GitHub Actions workflow job run conclusions.
This is taken from
https://docs.github.com/en/rest/actions/workflow-jobs?apiVersion=2022-11-28#get-a-job-for-a-workflow-run
as of 30.10.2023.
"""


def validate_conclusions(conclusions: list[str]) -> list[str]:
"""Validate the conclusions.
I.e., ensure they are valid GitHub Actions workflow job run conclusions.
"""
if not conclusions:
raise ValueError(
"No conclusions supplied - at least one is required (default: 'success')."
)

for conclusion in conclusions:
invalid_conclusions: list[str] = []
if conclusion not in VALID_CONCLUSIONS:
invalid_conclusions.append(conclusion)

if invalid_conclusions:
return [
f"Invalid supplied conclusions: {invalid_conclusions}. "
f"Valid conclusions are: {VALID_CONCLUSIONS}"
]

return conclusions

0 comments on commit ce8691d

Please sign in to comment.