Skip to content

Commit 0c7af3c

Browse files
authored
Merge pull request #35 from Expensify/Rory-ValidateGitHubActionsAnyRepo
Validate GitHub actions in any repo
2 parents 594ea29 + 863677e commit 0c7af3c

File tree

6 files changed

+100
-38
lines changed

6 files changed

+100
-38
lines changed

.github/scripts/actionlint.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ readonly SCRIPT_DIR
1515
# To update the actionlint version, replace this file with the updated checksums file from the GitHub release
1616
readonly CHECKSUMS_FILE="$SCRIPT_DIR/actionlint_checksums.txt"
1717
readonly ACTIONLINT_PATH="$SCRIPT_DIR/actionlint"
18+
readonly REPO_ROOT="${REPO_ROOT:-.}"
1819

1920
source "$SCRIPT_DIR/shellUtils.sh"
2021

@@ -72,16 +73,17 @@ else
7273
# It's only possible to have one exit trap, so we have to update to include both items we wish to remove
7374
trap 'rm -rf "$TMPDIR" "$TARBALL"' EXIT
7475
tar -C "$TMPDIR" -xzf "$TARBALL"
75-
mv "$TMPDIR/actionlint" "$SCRIPT_DIR/actionlint"
76+
mv "$TMPDIR/actionlint" "$ACTIONLINT_PATH"
7677

77-
INSTALLED_VERSION="$("$SCRIPT_DIR/actionlint" -version | head -n 1)"
78+
INSTALLED_VERSION="$("$ACTIONLINT_PATH" -version | head -n 1)"
7879
readonly INSTALLED_VERSION
7980
info "Successfully installed actionlint version $INSTALLED_VERSION" >&2
8081
fi
8182

8283
info "Linting workflows..."
8384
echo
84-
if ! "$SCRIPT_DIR/actionlint" -color; then
85+
cd "$REPO_ROOT" || exit 1
86+
if ! "$ACTIONLINT_PATH" -color; then
8587
error "Workflows did not pass actionlint :("
8688
exit 1
8789
fi

.github/scripts/shellUtils.sh

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,50 @@
22

33
# Check if GREEN has already been defined
44
if [ -z "${GREEN+x}" ]; then
5-
declare -r GREEN=$'\e[1;32m'
5+
readonly GREEN=$'\e[1;32m'
6+
fi
7+
8+
# Check if YELLOW has already been defined
9+
if [ -z "${YELLOW+x}" ]; then
10+
readonly YELLOW=$'\e[1;33m'
611
fi
712

813
# Check if RED has already been defined
914
if [ -z "${RED+x}" ]; then
10-
declare -r RED=$'\e[1;31m'
15+
readonly RED=$'\e[1;31m'
1116
fi
1217

1318
# Check if BLUE has already been defined
1419
if [ -z "${BLUE+x}" ]; then
15-
declare -r BLUE=$'\e[1;34m'
20+
readonly BLUE=$'\e[1;34m'
1621
fi
1722

1823
# Check if TITLE has already been defined
1924
if [ -z "${TITLE+x}" ]; then
20-
declare -r TITLE=$'\e[1;4;34m'
25+
readonly TITLE=$'\e[1;4;34m'
2126
fi
2227

2328
# Check if RESET has already been defined
2429
if [ -z "${RESET+x}" ]; then
25-
declare -r RESET=$'\e[0m'
30+
readonly RESET=$'\e[0m'
2631
fi
2732

28-
function success {
33+
function success() {
2934
echo "🎉 $GREEN$1$RESET"
3035
}
3136

32-
function error {
37+
function warning() {
38+
echo "⚠️ $YELLOW$1$RESET"
39+
}
40+
41+
function error() {
3342
echo "💥 $RED$1$RESET"
3443
}
3544

36-
function info {
45+
function info() {
3746
echo "$BLUE$1$RESET"
3847
}
3948

40-
function title {
49+
function title() {
4150
printf "\n%s%s%s\n" "$TITLE" "$1" "$RESET"
4251
}

.github/scripts/validateImmutableActionRefs.sh

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,31 @@
33
# Check for unsafe action references #
44
############################################
55

6-
GITHUB_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." &>/dev/null && pwd)"
7-
readonly GITHUB_DIR
6+
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
7+
readonly SCRIPT_DIR
88

9-
source "$GITHUB_DIR/scripts/shellUtils.sh"
9+
readonly REPO_ROOT="${REPO_ROOT:-.}"
10+
11+
source "$SCRIPT_DIR/shellUtils.sh"
1012

1113
title "Checking for mutable action references..."
1214

1315
ACTION_USAGES=""
1416

1517
# Find yaml files - these can be either:
1618
# - workflows, which are always stored in .github/workflows, or
17-
YAML_FILES="$(find "$GITHUB_DIR/workflows" -type f \( -name "*.yml" -o -name "*.yaml" \))"
19+
WORKFLOWS="$(find "$REPO_ROOT/.github/workflows" -type f \( -name "*.yml" -o -name "*.yaml" \))"
20+
if [[ -z "$WORKFLOWS" ]]; then
21+
warning "No workflows found. Did you remember to run this script from the root of a repository?" >&2
22+
fi
23+
1824
# - action metadata files, which can be anywhere in the repo, but must be called action.yml or action.yaml
19-
YAML_FILES+=" $(find "$GITHUB_DIR/.." -type f \( -name "action.yml" -o -name "action.yaml" \))"
25+
ACTIONS="$(find "$REPO_ROOT" -type f \( -name "action.yml" -o -name "action.yaml" \))"
26+
if [[ -z "$ACTIONS" ]]; then
27+
warning "No workflows found. Did you remember to run this script from the root of a repository?" >&2
28+
fi
29+
30+
readonly YAML_FILES="$WORKFLOWS $ACTIONS"
2031

2132
# Find yaml files in the `.github` directory
2233
for FILE in $YAML_FILES; do
@@ -74,7 +85,7 @@ function check_remote_ref() {
7485
local REPO
7586
REPO="$(echo "$ACTION" | awk -F/ '{print $1 "/" $2}')"
7687

77-
local REPO_URL="git@github.com:${REPO}.git"
88+
local REPO_URL="https://github.com/${REPO}"
7889
if git ls-remote --quiet --tags --heads --exit-code "$REPO_URL" "refs/*/$REF*" ; then
7990
error "Found remote branch or tag that looks like a commit hash! ${ACTION}@${REF}"
8091
return 1

.github/scripts/validateWorkflowSchemas.sh

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
# Validate GitHub action and workflow yaml schemas #
44
##########################################################
55

6-
GITHUB_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." &>/dev/null && pwd)"
7-
readonly GITHUB_DIR
6+
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
7+
readonly SCRIPT_DIR
88

9-
source "$GITHUB_DIR/scripts/shellUtils.sh"
9+
source "$SCRIPT_DIR/shellUtils.sh"
10+
11+
readonly REPO_ROOT="${REPO_ROOT:-.}"
1012

1113
title "Validating the Github Actions and workflows using the json schemas provided by (https://www.schemastore.org/json/)"
1214

@@ -21,7 +23,7 @@ for SCHEMA in github-action.json github-workflow.json; do
2123
if curl "https://json.schemastore.org/$SCHEMA" --output "$TEMP_SCHEMA_DIR/$SCHEMA" --silent; then
2224
success "Successfully downloaded $SCHEMA schema!"
2325
else
24-
error "Failed downloading $SCHEMA schema"
26+
error "Failed downloading $SCHEMA schema" >&2
2527
exit 1
2628
fi
2729
done
@@ -33,7 +35,10 @@ info "Validating action metadata files against their JSON schema..."
3335
echo
3436

3537
# Get all actions, delimited by -d (data arg for ajv)
36-
ACTIONS="$(find "$GITHUB_DIR/.." -type f \( -name "action.yml" -o -name "action.yaml" \) -exec echo -n " -d "{} \;)"
38+
ACTIONS="$(find "$REPO_ROOT" -type f \( -name "action.yml" -o -name "action.yaml" \) -exec echo -n " -d "{} \;)"
39+
if [[ -z "$ACTIONS" ]]; then
40+
warning "No actions found. Did you remember to run this script from the root of a repo?" >&2
41+
fi
3742

3843
# Disabling shellcheck because we WANT word-splitting on ACTIONS in this case
3944
# shellcheck disable=SC2086
@@ -46,7 +51,10 @@ info "Validating workflows against their JSON schema..."
4651
echo
4752

4853
# Get all workflows, delimited by -d (data arg for ajv)
49-
WORKFLOWS="$(find "$GITHUB_DIR/workflows" -type f \( -name "*.yml" -o -name "*.yaml" \) -exec echo -n " -d "{} \;)"\
54+
WORKFLOWS="$(find "${REPO_ROOT}/.github/workflows" -type f \( -name "*.yml" -o -name "*.yaml" \) -exec echo -n " -d "{} \;)"
55+
if [[ -z "$WORKFLOWS" ]]; then
56+
warning "No workflows found. Did you remember to run this script from the root of a repo?" >&2
57+
fi
5058

5159
# shellcheck disable=SC2086
5260
if ! npx ajv --strict=false -s "$TEMP_SCHEMA_DIR/github-workflow.json" $WORKFLOWS; then
@@ -56,7 +64,7 @@ fi
5664
echo
5765

5866
if [[ $EXIT_CODE -ne 0 ]]; then
59-
error "Some actions and/or workflows are invalid"
67+
error "Some actions and/or workflows are invalid" >&2
6068
exit $EXIT_CODE
6169
fi
6270

.github/workflows/validateActions.yml

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,37 +10,43 @@ jobs:
1010
validateSchemas:
1111
runs-on: ubuntu-latest
1212
steps:
13-
# v4.2.2
14-
- name: Checkout
15-
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
13+
- name: Checkout repos
14+
id: repo
15+
uses: Expensify/GitHub-Actions/checkoutRepoAndGitHubActions@main
1616

1717
# v4.3.0
1818
- name: Setup Node
1919
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e
2020

2121
# Install node to get the ajv-cli
2222
- name: Install node modules
23-
run: npm ci
23+
run: npm i -g ajv-cli@5.0.0
2424

2525
- name: Validate action and workflow schemas
26-
run: .github/scripts/validateWorkflowSchemas.sh
26+
run: GitHub-Actions/.github/scripts/validateWorkflowSchemas.sh
27+
env:
28+
REPO_ROOT: ${{ steps.repo.outputs.NAME }}
2729

2830
actionlint:
2931
runs-on: ubuntu-latest
3032
steps:
31-
# v4.2.2
32-
- name: Checkout
33-
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
33+
- name: Checkout repos
34+
id: repo
35+
uses: Expensify/GitHub-Actions/checkoutRepoAndGitHubActions@main
3436

3537
- name: Lint workflows with actionlint
36-
run: .github/scripts/actionlint.sh
38+
run: GitHub-Actions/.github/scripts/actionlint.sh
39+
env:
40+
REPO_ROOT: ${{ steps.repo.outputs.NAME }}
3741

3842
validateImmutableActionRefs:
3943
runs-on: ubuntu-latest
4044
steps:
41-
# v4.2.2
42-
- name: Checkout
43-
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
45+
- name: Checkout repos
46+
id: repo
47+
uses: Expensify/GitHub-Actions/checkoutRepoAndGitHubActions@main
4448

4549
- name: Validate actions refs are immutable
46-
run: .github/scripts/validateImmutableActionRefs.sh
50+
run: GitHub-Actions/.github/scripts/validateImmutableActionRefs.sh
51+
env:
52+
REPO_ROOT: ${{ steps.repo.outputs.NAME }}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: Checkout target repo and GitHub Actions repo
2+
3+
outputs:
4+
NAME:
5+
description: The target repo where this workflow is running (repo name w/o org prefix)
6+
value: ${{ steps.repo.outputs.NAME }}
7+
8+
runs:
9+
using: composite
10+
steps:
11+
- name: Get target repo name
12+
id: repo
13+
run: echo "NAME=$(basename ${{ github.repository }})" >> "$GITHUB_OUTPUT"
14+
shell: bash
15+
16+
# v4.2.2
17+
- name: Checkout
18+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
19+
with:
20+
path: ${{ steps.repo.outputs.NAME }}
21+
22+
- name: Checkout Expensify/GitHub-Actions
23+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
24+
with:
25+
repository: Expensify/GitHub-Actions
26+
path: GitHub-Actions

0 commit comments

Comments
 (0)