Skip to content

Commit

Permalink
feat: add branch protection list checks
Browse files Browse the repository at this point in the history
adds docs and script for branch protection
  • Loading branch information
BobyMCbobs committed Oct 3, 2023
1 parent 3894d12 commit 5191ded
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 0 deletions.
71 changes: 71 additions & 0 deletions branch-protections.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Branch protections

Repos branches are protected through requiring pull requests
and passing workflow jobs. All of the GeoNet repos have some
form of branch protection, whether that be just no write to main
and/or some checks from workflows that are in those repos.

## Behaviours

GitHub Actions workflows populate the
_Require status checks to pass before merging_ section of
project settings after they're run, so a new job can't be
required for protection until it's run.

The search is unhelpful due to it not populating the list of
checks when trying to search without typing.

## Determine a list of checks

Use the helper script to get a mostly-concreate set of values
which may be set to provide check-based branch merge protection.

List checks for all GeoNet repos

```sh
./hack/list-checks.sh
```

List checks for a specific GeoNet repos

```sh
./hack/list-checks.sh Actions base-images
```

Some example output may look like

```yaml
GeoNet/Actions:
- commit-digest-vet / presubmit-workflow
- conform/commit/commit-body
- conform/commit/conventional-commit
- conform/commit/header-case
- conform/commit/header-last-character
- conform/commit/header-length
- conform/commit/imperative-mood
- conform/commit/spellcheck
- conform / conform
- lint-markdown / markdown-lint
- presubmit-readme-toc / presubmit-readme-toc
- require-actions-run-from-GeoNet-org
- require-jobs-run-steps-have-name
- require-reusable-workflow-is-documented
- t0-basic / build
- t0-basic-check
- t1-use-test / build
- t1-use-test-check
- t2-artifact-pull / build
- t2-artifact-pull-cleanup
- t2-artifact-pull-prepare
- t3-multi-arch / build
- t3-multi-arch-check
- t6-auth-with-geonetci / build
- t6-auth-with-geonetci-check
- t7-use-setup / build
- t8-use-tags / build
- t8-use-tags-check
- t9-no-push / build
- t9-no-push-check
- validate-schema / validate-github-actions
GeoNet/base-images:
```
97 changes: 97 additions & 0 deletions hack/list-checks.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#!/bin/bash

set -o errexit
set -o nounset
set -o pipefail

REPOS="${@}"

DEBUG=false
__debug_echo() {
if [ ! "$DEBUG" = true ]; then
return
fi
echo "${@}"
}

get_repos_with_actions() {
repos=($(gh api orgs/GeoNet/repos --jq '.[] | select(.fork==false) | select(.archived==false) | .name' --paginate \
| sort \
| tr ' ' '\n' \
| xargs -I{} \
sh -c 'gh api "repos/GeoNet/{}/contents/.github/workflows" --jq ". | length | . > 0" 2>&1>/dev/null && echo GeoNet/{}' \
| grep -E '^GeoNet/.*' | cat))
echo "${repos[@]}"
}

get_pull_request_numbers() {
REPO="$1"
PULL_REQUEST_NUMBERS=()
while read NUMBER; do
PULL_REQUEST_NUMBERS+=("$NUMBER")
done < <(gh api -X GET "repos/$REPO/pulls" -f state=all --jq .[0].number)
echo "${PULL_REQUEST_NUMBERS[@]}"
}

get_head_ref_commit() {
REPO="$1"
NUMBER="$2"
commit="$(gh api "repos/$REPO/pulls/$NUMBER/commits" --jq '.[0].sha')"
echo "$commit"
}

get_status_checks() {
REPO="$1"
checks=()
for PR in $(get_pull_request_numbers "$REPO"); do
__debug_echo "$REPO/pull/$PR"
COMMIT="$(get_head_ref_commit "$REPO" "$PR")"
__debug_echo " - PR commit: $COMMIT"
while read CONTEXT; do
checks+=("$CONTEXT")
done < <(gh api "repos/$REPO/commits/$COMMIT/status" --jq '.statuses[].context')
done
CHECKS+=("${checks[@]}")
}

get_workflow_checks() {
REPO="$1"
checks=()
for PR in $(get_pull_request_numbers "$REPO"); do
__debug_echo "$REPO/pull/$PR"
COMMIT="$(get_head_ref_commit "$REPO" "$PR")"
__debug_echo " - PR commit: $COMMIT"
while read SUITE; do
__debug_echo " - Check suite: $SUITE"
while read RUN; do
__debug_echo " - Check run: $RUN"
checks+=("$RUN")
done < <(gh api "repos/$REPO/check-suites/$SUITE/check-runs" --jq .check_runs[].name)
done < <(gh api "repos/$REPO/commits/$COMMIT/check-suites" --jq .check_suites[].id)
done
CHECKS+=("${checks[@]}")
}

get_checks() {
REPO="$1"
echo "$REPO:"
CHECKS=()
get_status_checks "$REPO"
get_workflow_checks "$REPO"
(
for CHECK in "${CHECKS[@]}"; do
echo " - $CHECK"
done
) | sort | uniq
}

if [ -n "$REPOS" ]; then
for REPO in $REPOS; do
get_checks "GeoNet/$REPO"
done
exit $?
fi

for REPO in $(get_repos_with_actions); do
get_checks "$REPO"
done

0 comments on commit 5191ded

Please sign in to comment.