Skip to content

Commit 9b19bd9

Browse files
feat(ci): make shellcheck mandatory — add .shellcheckrc, fix 24 violations, add CI jobs
Adds shellcheck as a required CI gate across GitHub Actions and Gitea workflows. Changes: - .shellcheckrc: project-wide config (shell=bash, severity=warning, exclude SC1090/SC1091) - Fix SC2155 (declare+assign): debug.sh, migrate_benchmarks.sh, verify_constant_sync.sh - Fix SC2034 (unused vars): lane-runtime.sh, self-update-quality.sh, prompts-submodule.sh, fix-hardcoded-permissions.sh, fix_hardcoded_addresses.sh (dead code removed), test-governance-integration.sh, actions.sh (disable comment for intentional capture) - Fix SC2124 (array→string): deploy-to-servers.sh - .github/workflows/ci.yml: new mandatory 'shellcheck' job - .gitea/workflows/governance-check.yml: shellcheck step before governance tests Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent cc02c37 commit 9b19bd9

14 files changed

Lines changed: 77 additions & 29 deletions

.gitea/workflows/governance-check.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,21 @@ jobs:
3535
echo "SUBMODULE_INIT=failed"
3636
fi
3737
38+
- name: Run shellcheck on all shell scripts
39+
run: |
40+
set -euo pipefail
41+
if ! command -v shellcheck &>/dev/null; then
42+
apt-get update -qq && apt-get install -y shellcheck
43+
fi
44+
mapfile -t shell_files < <(git ls-files '*.sh' | sort)
45+
if [[ ${#shell_files[@]} -eq 0 ]]; then
46+
echo "No shell files found"
47+
exit 0
48+
fi
49+
echo "Checking ${#shell_files[@]} shell file(s)..."
50+
shellcheck -x "${shell_files[@]}"
51+
echo "shellcheck: all files passed"
52+
3853
- name: Run governance unit tests (70%)
3954
run: |
4055
set -euo pipefail

.github/workflows/ci.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,36 @@ PY
196196
run: |
197197
test -f outputs/ci/lint/report.json && cat outputs/ci/lint/report.json || true
198198
199+
shellcheck:
200+
name: shellcheck
201+
runs-on: ubuntu-latest
202+
timeout-minutes: 10
203+
permissions:
204+
contents: read
205+
steps:
206+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
207+
with:
208+
fetch-depth: 0
209+
210+
- name: Install shellcheck
211+
run: |
212+
sudo apt-get update -qq
213+
sudo apt-get install -y shellcheck
214+
215+
- name: Run shellcheck
216+
run: |
217+
set -euo pipefail
218+
mapfile -t shell_files < <(
219+
git ls-files '*.sh' | sort
220+
)
221+
if [[ ${#shell_files[@]} -eq 0 ]]; then
222+
echo "No shell files found"
223+
exit 0
224+
fi
225+
echo "Checking ${#shell_files[@]} shell file(s)..."
226+
shellcheck -x "${shell_files[@]}"
227+
echo "shellcheck: all files passed"
228+
199229
ci-unit:
200230
name: ci-unit
201231
runs-on: ubuntu-latest

.shellcheckrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# .shellcheckrc — shellcheck configuration for the eos project
2+
shell=bash
3+
enable=avoid-nullary-conditions,check-unassigned-uppercase,require-variable-braces
4+
severity=warning
5+
# SC1090: Can't follow non-constant source — safe with # shellcheck source= directives
6+
# SC1091: Not following source — safe in test mocks
7+
exclude=SC1090,SC1091

scripts/ci/debug.sh

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ lane_run_step "preflight" scripts/ci/preflight.sh
3838
lane_run_step "sanitize_git_env" ge_unset_git_local_env
3939
lane_run_step "git_conflict_guard" ensure_no_merge_conflicts
4040

41-
export PATH="$(go env GOPATH)/bin:${PATH}"
41+
_gopath="$(go env GOPATH)"
42+
export PATH="${_gopath}/bin:${PATH}"
4243
if ! command -v golangci-lint >/dev/null 2>&1; then
4344
lane_log "INFO" "ci_debug.bootstrap" "golangci-lint missing; installing pinned v2.0.0" "bootstrap"
4445
lane_run_step "install_golangci_lint" go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.0.0
@@ -99,9 +100,9 @@ lane_run_step "governance_propagation_shell_coverage" \
99100
-- bash -c 'bash test/ci/test-lane-runtime-unit.sh && bash test/ci/test-submodule-freshness.sh && bash test/ci/test-governance-check.sh'
100101
lane_run_step "verify_parity_contract_tests" bash test/ci/test-verify-parity.sh
101102

102-
CI_LANE_FAILED_STAGE="none"
103-
CI_LANE_FAILED_COMMAND=""
104-
CI_LANE_FAILED_LINE=0
105-
CI_LANE_FAILED_EXIT=0
106-
CI_LANE_STAGE="complete"
103+
export CI_LANE_FAILED_STAGE="none"
104+
export CI_LANE_FAILED_COMMAND=""
105+
export CI_LANE_FAILED_LINE=0
106+
export CI_LANE_FAILED_EXIT=0
107+
export CI_LANE_STAGE="complete"
107108
lane_finish "pass" "ci:debug completed successfully" 0

scripts/ci/lib/lane-runtime.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,6 @@ lane_on_err() {
171171
CI_LANE_FAILED_STAGE="${CI_LANE_STAGE}"
172172
CI_LANE_FAILED_COMMAND="${cmd}"
173173
CI_LANE_FAILED_LINE="${line}"
174-
CI_LANE_FAILED_EXIT="${exit_code}"
174+
export CI_LANE_FAILED_EXIT="${exit_code}"
175175
lane_finish "fail" "${CI_LANE_NAME} failed at stage ${CI_LANE_STAGE} line ${line}" "${exit_code}"
176176
}

scripts/ci/self-update-quality.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ awk -v cov="${focus_coverage}" -v min="${focus_threshold}" 'BEGIN { if (cov+0 <
104104
false
105105
}
106106

107-
CI_LANE_EXTRA_METRICS="# TYPE eos_self_update_quality_coverage_percent gauge
107+
export CI_LANE_EXTRA_METRICS="# TYPE eos_self_update_quality_coverage_percent gauge
108108
eos_self_update_quality_coverage_percent ${focus_coverage}
109109
# TYPE eos_self_update_quality_threshold_percent gauge
110110
eos_self_update_quality_threshold_percent ${focus_threshold}
@@ -115,7 +115,7 @@ eos_self_update_quality_integration_weight ${integration_weight}
115115
# TYPE eos_self_update_quality_e2e_weight gauge
116116
eos_self_update_quality_e2e_weight ${e2e_weight}"
117117

118-
CI_LANE_EXTRA_REPORT_FIELDS="coverage_percent=${focus_coverage}
118+
export CI_LANE_EXTRA_REPORT_FIELDS="coverage_percent=${focus_coverage}
119119
coverage_threshold=#int:${focus_threshold}
120120
weight_unit=#int:${unit_weight}
121121
weight_integration=#int:${integration_weight}

scripts/deploy-to-servers.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
set -euo pipefail
66

7-
SERVERS="${@:-vhost2}" # Default to vhost2, or use provided list
7+
SERVERS="${*:-vhost2}" # Default to vhost2, or use provided list
88
BUILD_DIR="/tmp/eos-deploy-$(date +%s)"
99
INSTALL_PATH="/usr/local/bin/eos"
1010

scripts/fix-hardcoded-permissions.sh

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,8 @@ CREATE_CONSTANTS_ONLY=false
2727
BACKUP_EXT=".permissions.bak"
2828
CONSTANTS_FILE="pkg/shared/permissions.go"
2929
REPLACED_COUNT=0
30-
SKIPPED_COUNT=0
3130

3231
# Colors for output
33-
RED='\033[0;31m'
3432
GREEN='\033[0;32m'
3533
YELLOW='\033[1;33m'
3634
BLUE='\033[0;34m'
@@ -243,7 +241,7 @@ for file in $FILES; do
243241

244242
# Check each replacement pattern
245243
for replacement in "${REPLACEMENTS[@]}"; do
246-
IFS=':' read -r octal_value constant_name usage <<< "$replacement"
244+
IFS=':' read -r octal_value constant_name _usage <<< "$replacement"
247245

248246
# Check if file contains this hardcoded value
249247
if grep -q "$octal_value" "$file"; then

scripts/fix_hardcoded_addresses.sh

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,6 @@
44

55
set -euo pipefail
66

7-
# Detect OS for sed compatibility
8-
if [[ "$OSTYPE" == "darwin"* ]]; then
9-
SED_INPLACE="sed -i ''"
10-
else
11-
SED_INPLACE="sed -i"
12-
fi
13-
147
# Colors for output
158
RED='\033[0;31m'
169
GREEN='\033[0;32m'

scripts/lib/prompts-submodule/actions.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ ps_capture_run() {
2323
# Ensure temp files are cleaned up on any exit path (including signals).
2424
trap 'rm -f "${stdout_file}" "${stderr_file}"' RETURN
2525
"$@" >"${stdout_file}" 2>"${stderr_file}" || rc=$?
26+
# PS_LAST_COMMAND_STDOUT is intentionally captured but not always used by callers.
27+
# shellcheck disable=SC2034
2628
PS_LAST_COMMAND_STDOUT="$(cat "${stdout_file}")"
2729
PS_LAST_COMMAND_STDERR="$(cat "${stderr_file}")"
2830
return "${rc}"

0 commit comments

Comments
 (0)