Skip to content

Commit

Permalink
build: provide ShellCheck shared workflow & template (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
kdmccormick authored Mar 10, 2023
1 parent fdf62bf commit 5f7cd28
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 0 deletions.
117 changes: 117 additions & 0 deletions .github/workflows/shellcheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# This is a reusable workflow for running ShellCheck,
# a linter for shell scripts (https://shellcheck.net).

# For more context, see:
# https://github.com/openedx/.github/blob/master/docs/decisions/0001-shellcheck.rst

name: ShellCheck

on:
workflow_call:
inputs:

exclude-patterns:
type: string
required: false
default: ""
description: |
File paths matching these patterns will be skipped when running ShellCheck.
Space-separated. Patterns containing spaces are not supported.
Wildcard asterisks (*) are supported.
This pattern will be matched against paths which all begin with './'; so,
in order to match any paths, your patterns should each begin with './' or '*'.
operating-system:
type: string
required: false
default: "ubuntu"
description: |
Operating system on which to run ShellCheck. Options are 'ubuntu' and 'macos'.
shellcheck-version:
type: string
required: false
default: "v0.9.0"
description:
ShellCheck version to install.
Must be a tag or branch of https://github.com/koalaman/shellcheck.
By default, the upstream action will use a reasonable, stable shellcheck version,
which will be updated over time as new stable ShellCheck versions come out.
If you want your repositoriy's build to be totally deterministic, though, then
override with a specific version pin here, and manage updates ShellCheck yourself.

shellcheck-options:
type: string
required: false
default: ""
description: |
Command-line options to forward to shellcheck.
For details of available options, run "shellcheck --help."
jobs:
shellcheck:

runs-on: "${{ inputs.operating-system }}-latest"

defaults:
run:
# Specifying bash ensures that `-o pipefail` (exit when the input to a pipeline fails) is enabled.
shell: bash

env:
SHELLCHECK_ARCHIVE: "" # We set this below based on operating-system.

steps:

- name: (Setup) Choose Linux AMD64 ShellCheck archive
if: inputs.operating-system == 'ubuntu'
run: echo "SHELLCHECK_ARCHIVE=shellcheck-${{ inputs.shellcheck-version }}.linux.x86_64.tar.xz" >> "$GITHUB_ENV"

- name: (Setup) Choose Darwin (macOS) AMD64 ShellCheck archive
if: inputs.operating-system == 'macos'
run: echo "SHELLCHECK_ARCHIVE=shellcheck-${{ inputs.shellcheck-version }}.darwin.x86_64.tar.xz" >> "$GITHUB_ENV"

- name: (Setup) Fail if we did not choose a ShellCheck archive
if: env.SHELLCHECK_ARCHIVE == ''
run: |
echo "::error::Error: Invalid input for operating-system: ${{ inputs.operating-system }}. Must be 'ubuntu' or 'macos'." && exit 1
- name: (Setup) Download & unpack ShellCheck
run: curl -L --fail --silent --show-error "https://github.com/koalaman/shellcheck/releases/download/${{ inputs.shellcheck-version }}/${{ env.SHELLCHECK_ARCHIVE }}" | tar --extract --xz

- name: (Setup) Install ShellCheck
run: sudo cp "shellcheck-${{ inputs.shellcheck-version }}/shellcheck" /usr/local/bin

- name: (Setup) Check out repository branch
uses: actions/checkout@v3

- name: Build the command for findings shell scripts
run: |
shellcheck_find_cmd="find . -name '*.sh'"
# Convert space-delimited exclude pattern into a proper array of exclusions,
# and then loop through that array in order to build the 'find' command.
read -r -a exclude_patterns <<<'${{ inputs.exclude-patterns }}'
for exclude_pattern in "${exclude_patterns[@]}" ; do
shellcheck_find_cmd="$shellcheck_find_cmd ! -wholename '$exclude_pattern'"
done
echo "SHELLCHECK_FIND_CMD=$shellcheck_find_cmd" >> "$GITHUB_ENV"
- name: Print helpful information
run: |
shellcheck -V
echo
echo "The following shell scripts will be checked:"
${{ env.SHELLCHECK_FIND_CMD }}
echo
echo "If ShellCheck passes, the next step will have no output."
echo "If ShellCheck fails, you should see a list of violations."
echo "Each violation type has an SCXXXX code which can be looked up at https://www.shellcheck.net/wiki/SCXXXX"
echo "We recommend that you try to resolve any violations."
echo "In the case where resolving the violation doesn't make sense, you can use directives (https://www.shellcheck.net/wiki/Directive) to ignore a single violation instance or an entire shell script."
echo
# This step is intentionally a big one-line command so that
# devs can easily copy it and run it on their own machine.
- name: Run ShellCheck
run: ${{ env.SHELLCHECK_FIND_CMD }} -print0 | xargs -0 shellcheck ${{ inputs.shellcheck-options }}

32 changes: 32 additions & 0 deletions workflow-templates/shellcheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Run ShellCheck on PRs and $default-branch

# For more context, see:
# https://github.com/openedx/.github/blob/master/docs/decisions/0001-shellcheck.rst

name: ShellCheck

on:
pull_request:
push:
branches:
- $default-branch

permissions:
contents: read

jobs:
shellcheck:
strategy:
matrix:
os: ["ubuntu", "macos"]
uses: openedx/.github/.github/workflows/shellcheck.yml@master
with:
# For details on the meaning of each of these arguments, see:
# https://github.com/openedx/.github/blob/master/.github/workflows/shellcheck.yml
# We exclude `./node_modules/*` by default because we want people to easily be able to
# copy and run the command locally. Local copies of most of our services have a `./node_modules`
# directory that we want to ignore.
exclude-patterns: "./node_modules/*"
operating-system: "${{ matrix.os }}"
#shellcheck-version: "v0.9.0"
#shellcheck-options: ""

0 comments on commit 5f7cd28

Please sign in to comment.