From 90b9d557d85aa0b32035e17d8b281b5d8801fd4a Mon Sep 17 00:00:00 2001 From: Kaj Kowalski Date: Mon, 5 Jan 2026 04:17:16 +0100 Subject: [PATCH] fix: quote shell variables in CI workflow for shellcheck compliance --- .github/workflows/ci.yml | 207 ++++++++++++++++++++------------------- 1 file changed, 108 insertions(+), 99 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2482750..2865352 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,13 +67,15 @@ jobs: env: CGO_ENABLED: 1 run: | - cat >> $GITHUB_STEP_SUMMARY << EOF + { + cat << EOF ## ๐Ÿ”ง Test Environment - **Go Version:** ${{ matrix.go }} - **OS:** ubuntu-latest - **Timestamp:** $(date -u) EOF + } >> "$GITHUB_STEP_SUMMARY" echo "Running tests with coverage..." task test:coverage 2>&1 | tee test-output.log @@ -86,16 +88,17 @@ jobs: SKIPPED_TESTS=$(grep -c "--- SKIP:" test-output.log || echo "0") # Generate test summary - cat >> $GITHUB_STEP_SUMMARY << EOF + { + cat << EOF ## ๐Ÿงช Test Results (Go ${{ matrix.go }}) - | Metric | Value | - | ----------- | ----------------------------------------------------------- | - | Total Tests | $TOTAL_TESTS | - | Passed | $PASSED_TESTS | - | Failed | $FAILED_TESTS | - | Skipped | $SKIPPED_TESTS | - | Status | $([ $TEST_STATUS -eq 0 ] && echo "PASSED" || echo "FAILED") | + | Metric | Value | + | ----------- | ------------------------------------------------------------- | + | Total Tests | $TOTAL_TESTS | + | Passed | $PASSED_TESTS | + | Failed | $FAILED_TESTS | + | Skipped | $SKIPPED_TESTS | + | Status | $([ "$TEST_STATUS" -eq 0 ] && echo "PASSED" || echo "FAILED") | ### ๐Ÿ“ฆ Package Test Results @@ -103,42 +106,43 @@ jobs: |---------|--------| EOF - # Extract package results - grep "^ok\|^FAIL" test-output.log | while read -r line; do - if [[ $line == ok* ]]; then - pkg=$(echo "$line" | awk '{print $2}') - echo "| $pkg | โœ… PASS |" >> $GITHUB_STEP_SUMMARY - elif [[ $line == FAIL* ]]; then - pkg=$(echo "$line" | awk '{print $2}') - echo "| $pkg | โŒ FAIL |" >> $GITHUB_STEP_SUMMARY - fi - done + # Extract package results + grep "^ok\|^FAIL" test-output.log | while read -r line; do + if [[ $line == ok* ]]; then + pkg=$(echo "$line" | awk '{print $2}') + echo "| $pkg | โœ… PASS |" + elif [[ $line == FAIL* ]]; then + pkg=$(echo "$line" | awk '{print $2}') + echo "| $pkg | โŒ FAIL |" + fi + done - echo "" >> $GITHUB_STEP_SUMMARY + echo "" - # Add detailed results if tests failed - if [ $TEST_STATUS -ne 0 ]; then - cat >> $GITHUB_STEP_SUMMARY << 'EOF' + # Add detailed results if tests failed + if [ "$TEST_STATUS" -ne 0 ]; then + cat << 'EOF' ### โŒ Failed Tests Details ``` EOF - grep -A 10 "--- FAIL:" test-output.log | head -100 >> $GITHUB_STEP_SUMMARY - cat >> $GITHUB_STEP_SUMMARY << 'EOF' + grep -A 10 -- "--- FAIL:" test-output.log | head -100 + cat << 'EOF' ``` EOF - fi + fi + } >> "$GITHUB_STEP_SUMMARY" # Set outputs for other steps - cat >> $GITHUB_OUTPUT << EOF - test-status=$TEST_STATUS - total-tests=$TOTAL_TESTS - passed-tests=$PASSED_TESTS - failed-tests=$FAILED_TESTS - EOF + { + echo "test-status=$TEST_STATUS" + echo "total-tests=$TOTAL_TESTS" + echo "passed-tests=$PASSED_TESTS" + echo "failed-tests=$FAILED_TESTS" + } >> "$GITHUB_OUTPUT" # Exit with the original test status - exit $TEST_STATUS + exit "$TEST_STATUS" - name: Generate coverage report if: always() @@ -146,7 +150,8 @@ jobs: if [ -f coverage/coverage.out ]; then COVERAGE=$(go tool cover -func=coverage/coverage.out | grep total | awk '{print $3}') - cat >> $GITHUB_STEP_SUMMARY << EOF + { + cat << EOF ## ๐Ÿ“Š Code Coverage (Go ${{ matrix.go }}) **Total Coverage: $COVERAGE** @@ -158,45 +163,46 @@ jobs: | ------- | -------- | EOF - # Create temporary file for package coverage aggregation - temp_coverage=$(mktemp) + # Create temporary file for package coverage aggregation + temp_coverage=$(mktemp) - # Extract package-level coverage data - go tool cover -func=coverage/coverage.out | grep -v total | while read -r line; do - if [[ $line == *".go:"* ]]; then - # Extract package path from file path (everything before the filename) - filepath=$(echo "$line" | awk '{print $1}') - pkg_path=$(dirname "$filepath" | sed 's|github.com/kjanat/articulate-parser/||; s|^\./||') - coverage=$(echo "$line" | awk '{print $3}' | sed 's/%//') + # Extract package-level coverage data + go tool cover -func=coverage/coverage.out | grep -v total | while read -r line; do + if [[ $line == *".go:"* ]]; then + # Extract package path from file path (everything before the filename) + filepath=$(echo "$line" | awk '{print $1}') + pkg_path=$(dirname "$filepath" | sed 's|github.com/kjanat/articulate-parser/||; s|^\./||') + coverage=$(echo "$line" | awk '{print $3}' | sed 's/%//') - # Use root package if no subdirectory - [[ "$pkg_path" == "." || "$pkg_path" == "" ]] && pkg_path="root" + # Use root package if no subdirectory + [[ "$pkg_path" == "." || "$pkg_path" == "" ]] && pkg_path="root" - echo "$pkg_path $coverage" >> "$temp_coverage" - fi - done + echo "$pkg_path $coverage" >> "$temp_coverage" + fi + done - # Aggregate coverage by package (average) - awk '{ - packages[$1] += $2 - counts[$1]++ - } - END { - for (pkg in packages) { - avg = packages[pkg] / counts[pkg] - printf "| %s | %.1f%% |\n", pkg, avg + # Aggregate coverage by package (average) + awk '{ + packages[$1] += $2 + counts[$1]++ } - }' "$temp_coverage" | sort >> $GITHUB_STEP_SUMMARY + END { + for (pkg in packages) { + avg = packages[pkg] / counts[pkg] + printf "| %s | %.1f%% |\n", pkg, avg + } + }' "$temp_coverage" | sort - rm -f "$temp_coverage" + rm -f "$temp_coverage" - cat >> $GITHUB_STEP_SUMMARY << 'EOF' + cat << 'EOF' EOF + } >> "$GITHUB_STEP_SUMMARY" else - cat >> $GITHUB_STEP_SUMMARY << 'EOF' + cat >> "$GITHUB_STEP_SUMMARY" << 'EOF' ## โš ๏ธ Coverage Report No coverage file generated @@ -215,52 +221,53 @@ jobs: - name: Run linters run: | - # Initialize summary - cat >> $GITHUB_STEP_SUMMARY << EOF + { + cat << EOF ## ๐Ÿ” Static Analysis (Go ${{ matrix.go }}) EOF - # Run go vet - VET_OUTPUT=$(task lint:vet 2>&1 || echo "") - VET_STATUS=$? + # Run go vet + VET_OUTPUT=$(task lint:vet 2>&1 || echo "") + VET_STATUS=$? - if [ $VET_STATUS -eq 0 ]; then - echo "โœ… **go vet:** No issues found" >> $GITHUB_STEP_SUMMARY - else - cat >> $GITHUB_STEP_SUMMARY << 'EOF' + if [ "$VET_STATUS" -eq 0 ]; then + echo "โœ… **go vet:** No issues found" + else + cat << 'EOF' โŒ **go vet:** Issues found ``` EOF - echo "$VET_OUTPUT" >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - fi - echo "" >> $GITHUB_STEP_SUMMARY + echo "$VET_OUTPUT" + echo '```' + fi + echo "" - # Run go fmt check - FMT_OUTPUT=$(task lint:fmt 2>&1 || echo "") - FMT_STATUS=$? + # Run go fmt check + FMT_OUTPUT=$(task lint:fmt 2>&1 || echo "") + FMT_STATUS=$? - if [ $FMT_STATUS -eq 0 ]; then - echo "โœ… **go fmt:** All files properly formatted" >> $GITHUB_STEP_SUMMARY - else - cat >> $GITHUB_STEP_SUMMARY << 'EOF' + if [ "$FMT_STATUS" -eq 0 ]; then + echo "โœ… **go fmt:** All files properly formatted" + else + cat << 'EOF' โŒ **go fmt:** Files need formatting ``` EOF - echo "$FMT_OUTPUT" >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - fi + echo "$FMT_OUTPUT" + echo '```' + fi + } >> "$GITHUB_STEP_SUMMARY" # Exit with error if any linter failed - [ $VET_STATUS -eq 0 ] && [ $FMT_STATUS -eq 0 ] || exit 1 + [ "$VET_STATUS" -eq 0 ] && [ "$FMT_STATUS" -eq 0 ] || exit 1 - name: Job Summary if: always() run: | - cat >> $GITHUB_STEP_SUMMARY << 'EOF' + cat >> "$GITHUB_STEP_SUMMARY" << 'EOF' ## ๐Ÿ“‹ Job Summary (Go ${{ matrix.go }}) | Step | Status | @@ -315,24 +322,26 @@ jobs: - name: Test Docker image using Task run: | - cat >> $GITHUB_STEP_SUMMARY << 'EOF' + { + cat << 'EOF' ## ๐Ÿงช Docker Image Tests EOF - # Run Task docker test - task docker:test + # Run Task docker test + task docker:test - echo "**Testing help command:**" >> $GITHUB_STEP_SUMMARY - echo '```terminaloutput' >> $GITHUB_STEP_SUMMARY - docker run --rm articulate-parser:latest --help >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY + echo "**Testing help command:**" + echo '```terminaloutput' + docker run --rm articulate-parser:latest --help + echo '```' + echo "" - # Test image size - IMAGE_SIZE=$(docker image inspect articulate-parser:latest --format='{{.Size}}' | numfmt --to=iec-i --suffix=B) - echo "**Image size:** $IMAGE_SIZE" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY + # Test image size + IMAGE_SIZE=$(docker image inspect articulate-parser:latest --format='{{.Size}}' | numfmt --to=iec-i --suffix=B) + echo "**Image size:** $IMAGE_SIZE" + echo "" + } >> "$GITHUB_STEP_SUMMARY" dependency-review: name: Dependency Review @@ -435,7 +444,7 @@ jobs: - name: Generate Docker summary run: | - cat >> $GITHUB_STEP_SUMMARY << 'EOF' + cat >> "$GITHUB_STEP_SUMMARY" << 'EOF' ## ๐Ÿณ Docker Build Summary **Image:** `ghcr.io/${{ github.repository }}`