Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/action-test-steps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ jobs:
- name: generate test coverage
run: go test ./... -coverprofile=./cover.out -covermode=atomic

- name: "test: entrypoint args"
run: make test-entrypoint

- name: set action to docker image
if: inputs.variant == 'docker'
run: |
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ test:
go test -timeout=3s -race -count=10 -failfast -shuffle=on -short ./...
go test -timeout=20s -race -count=1 -failfast -shuffle=on ./... -coverprofile=./cover.profile -covermode=atomic -coverpkg=./...

.PHONY: test-entrypoint
test-entrypoint:
bash scripts/test-entrypoint-args.sh

# Runs test coverage check
.PHONY: check-coverage
check-coverage: test
Expand Down
23 changes: 0 additions & 23 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -155,26 +155,3 @@ runs:
# TOOL_VERSION: when changing version update version in other places
image: docker://ghcr.io/vladopajic/go-test-coverage:v2.19.0
entrypoint: /docker-entrypoint.sh
env:
INPUT_CONFIG: ${{ inputs.config }}
INPUT_PROFILE: ${{ inputs.profile }}
INPUT_SOURCE_DIR: ${{ inputs.source-dir }}
INPUT_DEBUG: ${{ inputs.debug }}
INPUT_THRESHOLD_FILE: ${{ inputs.threshold-file }}
INPUT_THRESHOLD_PACKAGE: ${{ inputs.threshold-package }}
INPUT_THRESHOLD_TOTAL: ${{ inputs.threshold-total }}
INPUT_BREAKDOWN_FILE_NAME: ${{ inputs.breakdown-file-name }}
INPUT_DIFF_BASE_BREAKDOWN_FILE_NAME: ${{ inputs.diff-base-breakdown-file-name }}
INPUT_DIFF_THRESHOLD: ${{ inputs.diff-threshold }}
INPUT_BADGE_FILE_NAME: ${{ inputs.badge-file-name }}
INPUT_CDN_KEY: ${{ inputs.cdn-key }}
INPUT_CDN_SECRET: ${{ inputs.cdn-secret }}
INPUT_CDN_REGION: ${{ inputs.cdn-region }}
INPUT_CDN_ENDPOINT: ${{ inputs.cdn-endpoint }}
INPUT_CDN_FILE_NAME: ${{ inputs.cdn-file-name }}
INPUT_CDN_BUCKET_NAME: ${{ inputs.cdn-bucket-name }}
INPUT_CDN_FORCE_PATH_STYLE: ${{ inputs.cdn-force-path-style }}
INPUT_GIT_TOKEN: ${{ inputs.git-token }}
INPUT_GIT_BRANCH: ${{ inputs.git-branch }}
INPUT_GIT_REPOSITORY: ${{ inputs.git-repository }}
INPUT_GIT_FILE_NAME: ${{ inputs.git-file-name }}
13 changes: 13 additions & 0 deletions docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
#!/bin/bash
set -e

# Normalize runner-provided INPUT_* env var names: some runners (or invocations)
# expose inputs with hyphens (e.g. INPUT_THRESHOLD-FILE) which are not valid
# shell identifiers and thus not visible via $VAR. Convert any `INPUT_*` env
# variable that contains `-` to a duplicate name with `_` so the script can
# reference `INPUT_THRESHOLD_FILE` etc. This preserves existing behavior and
# improves compatibility with runners that don't normalise names.
while IFS='=' read -r name value; do
if [[ $name == INPUT_* && $name == *-* ]]; then
newname=${name//-/_}
export "$newname"="$value"
fi
done < <(env)

# Start building the command
args=(/go-test-coverage)

Expand Down
111 changes: 111 additions & 0 deletions scripts/run_action_tests_local.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT=$(cd "$(dirname "$0")/.." && pwd)
cd "$ROOT"

echo "Generating coverage profile..."
# Run tests but skip GitHub integration tests by clearing GITHUB_TOKEN
env GITHUB_TOKEN= go test ./... -coverprofile=./cover.out -covermode=atomic

tmp_output="$(mktemp)"
cleanup() { rm -f "$tmp_output"; }
trap cleanup EXIT

run_cmd() {
local id=$1
shift
local expect_fail=$1
shift
echo "-> Running $id: $*"
export GITHUB_OUTPUT="$tmp_output"
set +e
"$@"
rc=$?
set -e
if [ "$expect_fail" = "false" ]; then
if [ $rc -ne 0 ]; then
echo "[FAIL] $id: exited $rc but expected success"
return 1
fi
else
if [ $rc -eq 0 ]; then
echo "[FAIL] $id: exited 0 but expected failure"
return 1
fi
fi
echo "[OK] $id (rc=$rc)"
return 0
}

check_outputs_present() {
if ! grep -q '^total-coverage=' "$tmp_output"; then
echo "[FAIL] missing total-coverage in GITHUB_OUTPUT"
return 1
fi
if ! grep -q '^badge-color=' "$tmp_output"; then
echo "[FAIL] missing badge-color in GITHUB_OUTPUT"
return 1
fi
if ! grep -q '^badge-text=' "$tmp_output"; then
echo "[FAIL] missing badge-text in GITHUB_OUTPUT"
return 1
fi
if ! grep -q '^report=' "$tmp_output" && [ "$1" = "require-report" ]; then
echo "[FAIL] missing report in GITHUB_OUTPUT"
return 1
fi
echo "[OK] outputs present in GITHUB_OUTPUT"
}

# ensure no leftover artifacts from previous runs
rm -f coverage-badge.svg coverage.breakdown || true

CMD_BASE=(go run ./ --github-action-output=true)

# Test 1
run_cmd test-1 false "${CMD_BASE[@]}" --config=./.github/workflows/testdata/zero.yml || exit 1
check_outputs_present require-report || exit 1

# Test 2 (should fail)
run_cmd test-2 true "${CMD_BASE[@]}" --config=./.github/workflows/testdata/total100.yml || true
check_outputs_present "" || true

# Test 3
run_cmd test-3 false "${CMD_BASE[@]}" --profile=cover.out --threshold-file=0 --threshold-package=0 --threshold-total=0 || exit 1

# Test 4 (should fail)
run_cmd test-4 true "${CMD_BASE[@]}" --profile=cover.out --threshold-file=0 --threshold-package=0 --threshold-total=100 || true

# Test 5
run_cmd test-5 false "${CMD_BASE[@]}" --config=./.github/workflows/testdata/total100.yml --threshold-file=0 --threshold-package=0 --threshold-total=0 || exit 1

# Test 6 (debug, missing profile => fail)
run_cmd test-6 true "${CMD_BASE[@]}" --profile=nonexistent-profile.out --debug=true --threshold-file=0 --threshold-package=0 --threshold-total=100 || true

# Test 7 (threshold-file failure)
run_cmd test-7 true "${CMD_BASE[@]}" --profile=cover.out --threshold-file=100 --threshold-package=0 --threshold-total=0 || true

# Test 8 (threshold-package failure)
run_cmd test-8 true "${CMD_BASE[@]}" --profile=cover.out --threshold-file=0 --threshold-package=100 --threshold-total=0 || true

# Test 9 (badge file generation)
run_cmd test-9 false "${CMD_BASE[@]}" --config=./.github/workflows/testdata/zero.yml --badge-file-name=coverage-badge.svg || exit 1
if [ ! -f coverage-badge.svg ]; then echo "[FAIL] badge file not created"; exit 1; fi
echo "[OK] badge file created"

# Test 10 (breakdown file)
run_cmd test-10 false "${CMD_BASE[@]}" --config=./.github/workflows/testdata/zero.yml --breakdown-file-name=coverage.breakdown || exit 1
if [ ! -f coverage.breakdown ]; then echo "[FAIL] breakdown file not created"; exit 1; fi
echo "[OK] breakdown file created"

# Test 11 (diff with base breakdown)
run_cmd test-11 false "${CMD_BASE[@]}" --config=./.github/workflows/testdata/zero.yml --diff-base-breakdown-file-name=coverage.breakdown || exit 1

# Test 12 (diff threshold failure)
run_cmd test-12 true "${CMD_BASE[@]}" --config=./.github/workflows/testdata/zero.yml --diff-base-breakdown-file-name=coverage.breakdown --diff-threshold=100 || true

# Test 13 (missing profile without debug -> fail)
run_cmd test-13 true "${CMD_BASE[@]}" --profile=nonexistent-profile.out --threshold-file=0 --threshold-package=0 --threshold-total=0 || true

echo "All local action-test-steps ran (see above for failures expected)."
89 changes: 89 additions & 0 deletions scripts/test-entrypoint-args.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#!/usr/bin/env bash
set -euo pipefail

# Comprehensive entrypoint args validation tests.
# For each scenario, we simulate runner-provided env vars (including hyphenated
# names via `env 'NAME=val'`) and assert the expected args are printed by a
# copy of `docker-entrypoint.sh` that prints args instead of execing the binary.

tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT

cp "$(pwd)/docker-entrypoint.sh" "$tmpdir/entrypoint.sh"
sed -i.bak 's|^exec .*|printf "%s\n" "${args[@]}"|' "$tmpdir/entrypoint.sh"
chmod +x "$tmpdir/entrypoint.sh"

failures=0

run_case() {
local name="$1"; shift
local envcmd=(env)
local expect=()
local not_expect=()

# Parse arguments: env=..., include=..., exclude=...
while (($#)); do
case "$1" in
env=*) envcmd+=("${1#env=}"); shift;;
include=*) expect+=("${1#include=}"); shift;;
exclude=*) not_expect+=("${1#exclude=}"); shift;;
*) echo "Unknown token $1"; exit 2;;
esac
done

echo "-- CASE: $name"
out=$("${envcmd[@]}" "$tmpdir/entrypoint.sh") || true
echo "$out" | sed 's/^/ /'

for e in "${expect[@]}"; do
if ! echo "$out" | grep -Fxq -- "$e"; then
echo "[FAIL] expected to find: $e"
failures=$((failures+1))
else
echo "[OK] found: $e"
fi
done

for ne in "${not_expect[@]}"; do
if echo "$out" | grep -Fxq -- "$ne"; then
echo "[FAIL] did not expect: $ne"
failures=$((failures+1))
else
echo "[OK] not present: $ne"
fi
done
}

# Cases
run_case "underscore threshold" env='INPUT_THRESHOLD_FILE=5' include='--threshold-file=5' exclude='--threshold-file=-1'

run_case "hyphenated threshold" env='INPUT_THRESHOLD-FILE=7' include='--threshold-file=7' exclude='--threshold-file=-1'

run_case "threshold sentinel -1" env='INPUT_THRESHOLD_FILE=-1' exclude='--threshold-file=-1' exclude='--threshold-file=0'

run_case "diff threshold sentinel -101" env='INPUT_DIFF_THRESHOLD=-101' exclude='--diff-threshold=-101'

run_case "diff threshold value" env='INPUT_DIFF_THRESHOLD=100' include='--diff-threshold=100'

run_case "debug true" env='INPUT_DEBUG=true' include='--debug=true'

run_case "debug false (absent)" exclude='--debug=true'

run_case "cdn force path style true" env='INPUT_CDN_FORCE_PATH_STYLE=true' include='--cdn-force-path-style=true'

run_case "cdn hyphenated file name" env='INPUT_CDN-FILE-NAME=test.svg' include='--cdn-file-name=test.svg'

run_case "git repository hyphenated" env='INPUT_GIT-REPOSITORY=owner/repo' include='--git-repository=owner/repo'

run_case "badge file name" env='INPUT_BADGE_FILE_NAME=coverage.svg' include='--badge-file-name=coverage.svg'

run_case "profile set" env='INPUT_PROFILE=cover.out' include='--profile=cover.out'

# Summary
if ((failures==0)); then
echo "All entrypoint args tests passed"
exit 0
else
echo "Entry point args tests had $failures failures"
exit 2
fi
31 changes: 31 additions & 0 deletions scripts/test-entrypoint-normalize.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -euo pipefail

# Simple unit test for docker-entrypoint.sh normalization of hyphenated INPUT_*
# environment variables. Copies the real entrypoint, replaces the final exec
# with a printf of the args, then runs it with a hyphenated env var and asserts
# the underscore-style flag is present.

tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT

cp "$(pwd)/docker-entrypoint.sh" "$tmpdir/entrypoint.sh"
cp "$(pwd)/docker-entrypoint.sh" "$tmpdir/entrypoint.sh"
# Replace the final exec line robustly (match a line starting with exec)
sed -i.bak 's|^exec .*|printf "%s\\n" "${args[@]}"|' "$tmpdir/entrypoint.sh"
chmod +x "$tmpdir/entrypoint.sh"

# Run the modified entrypoint with a hyphenated INPUT_* env var (simulate runner)
# Note: shells cannot export hyphenated names, but `env 'NAME=val' cmd` can simulate it.
out=$(env 'INPUT_THRESHOLD-FILE=42' "$tmpdir/entrypoint.sh")

echo "Entrypoint output:"
echo "$out"

if echo "$out" | grep -q -- "--threshold-file=42"; then
echo "[OK] normalization produced expected --threshold-file flag"
exit 0
else
echo "[FAIL] expected --threshold-file=42 in output"
exit 2
fi