diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml new file mode 100644 index 0000000..34f3d2b --- /dev/null +++ b/.github/workflows/codespell.yml @@ -0,0 +1,16 @@ +--- +name: Codespell + +# Always run on Pull Requests +on: # yamllint disable-line rule:truthy + pull_request: + +jobs: + pylint: + name: Run Codespell + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + - name: Run check + uses: codespell-project/actions-codespell@master diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml new file mode 100644 index 0000000..130131e --- /dev/null +++ b/.github/workflows/shellcheck.yml @@ -0,0 +1,31 @@ +--- +name: ShellCheck + +# Always run on Pull Requests +on: # yamllint disable-line rule:truthy + pull_request: + +jobs: + pylint: + name: Run ShellCheck + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Install core packages + run: | + ./tests/install_shellcheck_ubuntu.sh + - name: Pull via git + run: | + git fetch origin ${{ github.event.pull_request.base.sha }} + - name: Show git diff + run: | + git diff --name-only ${{ github.event.pull_request.base.sha }} + - name: Do the ShellCheck + run: | + base_sha="${{ github.event.pull_request.base.sha }}" + changed="$(git diff --name-only $base_sha)" + export CHANGED_FILES="$changed" + ./tests/pre-commit_d/shellcheck_check.sh diff --git a/.github/workflows/xmllint.yml b/.github/workflows/xmllint.yml new file mode 100644 index 0000000..22ff1e3 --- /dev/null +++ b/.github/workflows/xmllint.yml @@ -0,0 +1,32 @@ +--- +name: Xmllint + +# Always run on Pull Requests +on: # yamllint disable-line rule:truthy + pull_request: + +jobs: + pylint: + name: Run Xmllint + # Oddly ubuntu-latest is older than 22.04 right now. + runs-on: ubuntu-22.04 + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Install core packages + run: | + ./tests/install_xmllint_ubuntu.sh + - name: Pull via git + run: | + git fetch origin ${{ github.event.pull_request.base.sha }} + - name: Show git diff + run: | + git diff --name-only ${{ github.event.pull_request.base.sha }} + - name: Do the pylint + run: | + base_sha="${{ github.event.pull_request.base.sha }}" + changed="$(git diff --name-only $base_sha)" + export CHANGED_FILES="$changed" + ./tests/pre-commit_d/xmllint_check.sh diff --git a/.github/workflows/yamllint.yml b/.github/workflows/yamllint.yml new file mode 100644 index 0000000..67bbc8b --- /dev/null +++ b/.github/workflows/yamllint.yml @@ -0,0 +1,18 @@ +--- +name: Yamllint + +# Always run on Pull Requests +on: # yamllint disable-line rule:truthy + - pull_request + +jobs: + yamllint: + name: Run Yamllint + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + - name: 'Yamllint' + uses: karancode/yamllint-github-action@master + with: + yamllint_comment: false diff --git a/README.md b/README.md index f91b0bb..94b2c7e 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,13 @@ -# forms -Forms used by D-Rats and possibly other programs +# D-Rats Forms + +Forms used by D-Rats and possibly other programs. + +These forms consist of XML file describing the form and an optional XSL for a +style sheet for the form. + +This is planned to allow D-Rats users to periodically update their forms. + +Advanced maintainers can copy the tests/pre-commit script to inside of the +.git/hooks directory which if the proper tools are installed, will test the +format of the files in a git commit action. This requires shellcheck, +yamllint, and codespell to be installed. diff --git a/tests/install_shellcheck_ubuntu.sh b/tests/install_shellcheck_ubuntu.sh new file mode 100755 index 0000000..a301fae --- /dev/null +++ b/tests/install_shellcheck_ubuntu.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# This is for use in a dockerfile or a github action to make sure +# that the required packages are installed. + +set -uex + +# Need to disable are-you-sure prompts during the installs +DEBIAN_FRONTEND=noninteractive +export DEBIAN_FRONTEND +# echo "APT::Get::Assume-Yes \"true\";" > /etc/apt/apt.conf.d/no-prompt +# echo "APT::Install-Recommends \"false\";" > \ +# /etc/apt/apt.conf.d/no-recommends + +# Update to current and add packages +sudo -S -E apt-get --assume-yes update +sudo -S -E apt-get --assume-yes install aptitude +sudo -S -E aptitude --assume-yes safe-upgrade +sudo -S -E apt-get --assume-yes install \ + file \ + git \ + grep \ + shellcheck diff --git a/tests/install_xmllint_ubuntu.sh b/tests/install_xmllint_ubuntu.sh new file mode 100755 index 0000000..96e3eff --- /dev/null +++ b/tests/install_xmllint_ubuntu.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# This is for use in a dockerfile or a github action to make sure +# that the required packages are installed. + +set -uex + +# Need to disable are-you-sure prompts during the installs +DEBIAN_FRONTEND=noninteractive +export DEBIAN_FRONTEND +# echo "APT::Get::Assume-Yes \"true\";" > /etc/apt/apt.conf.d/no-prompt +# echo "APT::Install-Recommends \"false\";" > \ +# /etc/apt/apt.conf.d/no-recommends + +# Update to current and add packages +sudo -S -E apt-get --assume-yes update +sudo -S -E apt-get --assume-yes install aptitude +sudo -S -E aptitude --assume-yes safe-upgrade +sudo -S -E apt-get --assume-yes install \ + file \ + git \ + grep \ + libxml2-utils diff --git a/tests/pre-commit b/tests/pre-commit new file mode 100755 index 0000000..366fed4 --- /dev/null +++ b/tests/pre-commit @@ -0,0 +1,55 @@ +#!/bin/bash + +# First part based on the pre-commit sample +set -ue + +if git rev-parse --verify HEAD >/dev/null 2>&1; then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --bool hooks.allownonascii) || true + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test "$(git diff --cached --name-only --diff-filter=A -z "$against" | + LC_ALL=C tr -d '[ -~]\0' | wc -c)" != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +git diff-index --check --cached "$against" -- + +CHANGED_FILES=$(git diff --name-only --cached --diff-filter=ACMR) +export CHANGED_FILES + +rc=0 +for check_script in tests/pre-commit_d/*; do + if ! "${check_script}"; then + (( rc=rc+PIPESTATUS[0] )) + fi +done +exit "$rc" diff --git a/tests/pre-commit_d/codespell_check.sh b/tests/pre-commit_d/codespell_check.sh new file mode 100755 index 0000000..91b452a --- /dev/null +++ b/tests/pre-commit_d/codespell_check.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +set -ue + +# Default list of files to lint +: "${CHANGED_FILES:=}" +if [ -z "$CHANGED_FILES" ]; then + # Nothing to do + exit 0 +fi + +# Default output +: "${CODESPELL_OUT:=codespell.log}" +# Default directory to start check +: "${BASE_DIR:=.}" + +# Now search for all shell script files +rc=0 +pushd "${BASE_DIR}" > /dev/null || exit 1 + + rm -f "${CODESPELL_OUT}" + + if ! codespell="$(command -v codespell)"; then + echo "codespell not found" + exit 0 + fi + + for script_file in ${CHANGED_FILES}; do + IFS=" " read -r -a codespell_cmd <<< "${codespell} ${script_file}" + if ! "${codespell_cmd[@]}" >> "${CODESPELL_OUT}" 2>&1; then + (( rc=rc+PIPESTATUS[0] )) + fi + done + + if [ "$rc" -ne 0 ] && [ -e "${CODESPELL_OUT}" ]; then + if ! grep ':' "${CODESPELL_OUT}"; then + # We have something not reported above? + cat "${CODESPELL_OUT}" + fi + fi +popd > /dev/null || exit 1 +exit "${rc}" diff --git a/tests/pre-commit_d/shellcheck_check.sh b/tests/pre-commit_d/shellcheck_check.sh new file mode 100755 index 0000000..22b9176 --- /dev/null +++ b/tests/pre-commit_d/shellcheck_check.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +set -ue + +# Default list of files to lint +: "${CHANGED_FILES:=}" +if [ -z "$CHANGED_FILES" ]; then + # Nothing to do + exit 0 +fi + +# Default output +: "${SHELLCHECK_OUT:=shellcheck.log}" +# Default directory to start check +: "${BASE_DIR:=.}" + +# Follow external references if shellcheck supports it. +external= +if (shellcheck --help | grep "\-\-external") &> /dev/null; then + external=--external +fi + +# Now search for all shell script files +rc=0 +pushd "${BASE_DIR}" > /dev/null || exit 1 + + rm -f "${SHELLCHECK_OUT}" + + # Template to allow other tools to parse the output + tmpl="--format=gcc" + + if ! shellcheck="$(command -v shellcheck)"; then + echo "shellcheck not found" + exit 0 + fi + + for script_file in ${CHANGED_FILES}; do + + IFS=" " read -r -a shellcheck_cmd <<< \ + "${shellcheck} ${external} ${script_file}" + if file "$script_file" | grep -q -e 'shell script'; then + if ! "${shellcheck_cmd[@]}" "${tmpl}" >> "${SHELLCHECK_OUT}" 2>&1; then + (( rc=rc+PIPESTATUS[0] )) + fi + fi + done + if [ "$rc" -ne 0 ] && [ -e "${SHELLCHECK_OUT}" ]; then + if ! grep ':' "${SHELLCHECK_OUT}"; then + cat "${SHELLCHECK_OUT}" + fi + fi +popd > /dev/null || exit 1 +exit "${rc}" diff --git a/tests/pre-commit_d/xmllint_check.sh b/tests/pre-commit_d/xmllint_check.sh new file mode 100755 index 0000000..c833b73 --- /dev/null +++ b/tests/pre-commit_d/xmllint_check.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +set -ue + +# Default list of files to lint +: "${CHANGED_FILES:=}" +if [ -z "$CHANGED_FILES" ]; then + # Nothing to do + exit 0 +fi + +# Default output +: "${XMLLINT_OUT:=xmllint.log}" +# Default directory to start check +: "${BASE_DIR:=.}" + +# Now search for all shell script files +rc=0 +pushd "${BASE_DIR}" > /dev/null || exit 1 + + rm -f "${XMLLINT_OUT}" + + if ! xmllint="$(command -v xmllint)"; then + echo "xmllint not found" + exit 0 + fi + + for script_file in ${CHANGED_FILES}; do + + IFS=" " read -r -a xmllint_cmd <<< \ + "${xmllint} --noout ${script_file}" + if file "$script_file" | grep -q -E '(XML|HTML)\s.*document'; then + if ! "${xmllint_cmd[@]}" >> "${XMLLINT_OUT}" 2>&1; then + (( rc=rc+PIPESTATUS[0] )) + fi + fi + done + if [ "$rc" -ne 0 ] && [ -e "${XMLLINT_OUT}" ]; then + if ! grep ':' "${XMLLINT_OUT}"; then + cat "${XMLLINT_OUT}" + fi + fi +popd > /dev/null || exit 1 +exit "${rc}" diff --git a/tests/pre-commit_d/yamllint_check.sh b/tests/pre-commit_d/yamllint_check.sh new file mode 100755 index 0000000..256ba3c --- /dev/null +++ b/tests/pre-commit_d/yamllint_check.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +set -ue + +# Default list of files to lint +: "${CHANGED_FILES:=}" +if [ -z "$CHANGED_FILES" ]; then + # Nothing to do + exit 0 +fi + +# Default output +: "${YAMLLINT_OUT:=yamllint.log}" +# Default directory to start check +: "${BASE_DIR:=.}" + +# Now search for all shell script files +rc=0 +pushd "${BASE_DIR}" > /dev/null || exit 1 + + rm -f "${YAMLLINT_OUT}" + + if ! yamllint="$(command -v yamllint)"; then + echo "yamllint not found" + exit 0 + fi + + for script_file in ${CHANGED_FILES}; do + + IFS=" " read -r -a yamllint_cmd <<< \ + "${yamllint} --strict --format github ${script_file}" + if [[ "$script_file" == *.yml ]]; then + if ! "${yamllint_cmd[@]}" >> "${YAMLLINT_OUT}" 2>&1; then + (( rc=rc+PIPESTATUS[0] )) + fi + fi + done + if [ "$rc" -ne 0 ] && [ -e "${YAMLLINT_OUT}" ]; then + if ! grep '::' "${YAMLLINT_OUT}"; then + cat "${YAMLLINT_OUT}" + fi + fi +popd > /dev/null || exit 1 +exit "${rc}"