Skip to content

Commit 7c3a48c

Browse files
authored
Merge pull request OtowoOrg#485 from yinkscss/fix/479-add-shell-script-linting-gate-for-scripts-folder
[479] Add shell script linting gate for scripts folder
2 parents 36837b7 + 30c1512 commit 7c3a48c

5 files changed

Lines changed: 95 additions & 17 deletions

File tree

.commitlintrc.yaml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@ rules:
1616
- style
1717
- test
1818
subject-case:
19+
- 0
20+
body-max-line-length:
1921
- 2
2022
- always
21-
- - sentence-case
22-
- start-case
23-
- pascal-case
24-
- upper-case
25-
- lower-case
23+
- 200

.github/workflows/ci.yml

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ concurrency:
1313
env:
1414
CARGO_TERM_COLOR: always
1515
RUST_BACKTRACE: 1
16+
SHELLCHECK_EXCLUDES: ""
1617
REGISTRY: ghcr.io
1718
IMAGE_NAME: ${{ github.repository }}
1819

@@ -24,6 +25,9 @@ jobs:
2425
docker: ${{ steps.detect.outputs.docker }}
2526
helm: ${{ steps.detect.outputs.helm }}
2627
api_docs: ${{ steps.detect.outputs.api_docs }}
28+
rust_core: ${{ steps.detect.outputs.rust_core }}
29+
deps: ${{ steps.detect.outputs.deps }}
30+
examples: ${{ steps.detect.outputs.examples }}
2731
steps:
2832
- uses: actions/checkout@v4
2933
- name: Detect Docker-impacting changes
@@ -51,7 +55,8 @@ jobs:
5155
echo "Changed files:"
5256
echo "$CHANGED_FILES"
5357
54-
if echo "$CHANGED_FILES" | grep -Eq '^(Dockerfile|\.dockerignore|Cargo\.toml|Cargo\.lock|src/|config/|Makefile)'; then
58+
DOCKER_PATTERN='^(Dockerfile|\.dockerignore|Cargo\.toml|Cargo\.lock|src/|config/|Makefile)'
59+
if echo "$CHANGED_FILES" | grep -Eq "$DOCKER_PATTERN"; then
5560
echo "docker=true" >> "$GITHUB_OUTPUT"
5661
else
5762
echo "docker=false" >> "$GITHUB_OUTPUT"
@@ -63,12 +68,31 @@ jobs:
6368
echo "helm=false" >> "$GITHUB_OUTPUT"
6469
fi
6570
66-
if echo "$CHANGED_FILES" | grep -Eq '^(docs/|scripts/generate-api-docs\.py|config/crd/|src/crd/|src/rest_api/|Makefile)'; then
71+
API_DOCS_PATTERN='^(docs/|scripts/generate-api-docs\.py|config/crd/|src/crd/|src/rest_api/|Makefile)'
72+
if echo "$CHANGED_FILES" | grep -Eq "$API_DOCS_PATTERN"; then
6773
echo "api_docs=true" >> "$GITHUB_OUTPUT"
6874
else
6975
echo "api_docs=false" >> "$GITHUB_OUTPUT"
7076
fi
7177
78+
if echo "$CHANGED_FILES" | grep -Eq '^(src/|Cargo\.toml|Cargo\.lock|Makefile|build\.rs)'; then
79+
echo "rust_core=true" >> "$GITHUB_OUTPUT"
80+
else
81+
echo "rust_core=false" >> "$GITHUB_OUTPUT"
82+
fi
83+
84+
if echo "$CHANGED_FILES" | grep -Eq '^(Cargo\.toml|Cargo\.lock)'; then
85+
echo "deps=true" >> "$GITHUB_OUTPUT"
86+
else
87+
echo "deps=false" >> "$GITHUB_OUTPUT"
88+
fi
89+
90+
if echo "$CHANGED_FILES" | grep -Eq '^(examples/|config/crd/|config/samples/)'; then
91+
echo "examples=true" >> "$GITHUB_OUTPUT"
92+
else
93+
echo "examples=false" >> "$GITHUB_OUTPUT"
94+
fi
95+
7296
version-consistency:
7397
name: Version Consistency Check
7498
if: github.event_name != 'pull_request'
@@ -102,12 +126,14 @@ jobs:
102126
echo "stellar-operator version output: $BIN_VERSION"
103127
104128
[[ "$CARGO_VERSION" == "$EXPECTED_VERSION" ]] || {
105-
echo "::error::Cargo.toml version ($CARGO_VERSION) does not match expected release version ($EXPECTED_VERSION)"
129+
echo "::error::Cargo.toml version ($CARGO_VERSION) does not match expected release version"
130+
echo "::error::Expected: $EXPECTED_VERSION"
106131
exit 1
107132
}
108133
109134
[[ "$BIN_VERSION" == "$EXPECTED_VERSION" ]] || {
110-
echo "::error::stellar-operator version output ($BIN_VERSION) does not match expected release version ($EXPECTED_VERSION)"
135+
echo "::error::stellar-operator version output ($BIN_VERSION) does not match expected release version"
136+
echo "::error::Expected: $EXPECTED_VERSION"
111137
exit 1
112138
}
113139
@@ -168,7 +194,9 @@ jobs:
168194
169195
examples-smoke-test:
170196
name: Examples Smoke Test
197+
if: needs.changes.outputs.examples == 'true'
171198
runs-on: ubuntu-latest
199+
needs: [changes]
172200
steps:
173201
- uses: actions/checkout@v4
174202

@@ -199,7 +227,9 @@ jobs:
199227
200228
security-audit:
201229
name: Security Audit
230+
if: needs.changes.outputs.deps == 'true'
202231
runs-on: ubuntu-latest
232+
needs: [changes]
203233
steps:
204234
- uses: actions/checkout@v4
205235

@@ -217,6 +247,7 @@ jobs:
217247
lint:
218248
name: Lint & Format
219249
runs-on: ubuntu-latest
250+
needs: [changes]
220251
steps:
221252
- uses: actions/checkout@v4
222253

@@ -238,17 +269,24 @@ jobs:
238269
239270
- name: Run shellcheck
240271
run: |
241-
mapfile -t shell_files < <(find . -type f -name "*.sh")
272+
mapfile -t shell_files < <(find scripts -type f -name "*.sh")
242273
if [ "${#shell_files[@]}" -eq 0 ]; then
243-
echo "No shell scripts found"
274+
echo "No shell scripts found in scripts/"
244275
exit 0
245276
fi
246-
shellcheck -S error "${shell_files[@]}"
277+
shellcheck_cmd=(shellcheck -S error)
278+
if [ -n "${SHELLCHECK_EXCLUDES}" ]; then
279+
shellcheck_cmd+=(-e "${SHELLCHECK_EXCLUDES}")
280+
echo "Running shellcheck with excludes: ${SHELLCHECK_EXCLUDES}"
281+
fi
282+
"${shellcheck_cmd[@]}" "${shell_files[@]}"
247283
248284
- name: Check formatting
285+
if: needs.changes.outputs.rust_core == 'true'
249286
run: make fmt-check
250287

251288
- name: Run clippy
289+
if: needs.changes.outputs.rust_core == 'true'
252290
run: make lint
253291

254292
test:

.github/workflows/pre-commit.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,12 @@ jobs:
3030
run: pip install pre-commit
3131

3232
- name: Run pre-commit
33-
run: pre-commit run --all-files --show-diff-on-failure
33+
run: |
34+
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
35+
BASE_SHA="${{ github.event.pull_request.base.sha }}"
36+
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
37+
git fetch --no-tags origin "$BASE_SHA" "$HEAD_SHA"
38+
pre-commit run --from-ref "$BASE_SHA" --to-ref "$HEAD_SHA" --show-diff-on-failure
39+
else
40+
pre-commit run --all-files --show-diff-on-failure
41+
fi

.github/workflows/verify-operator-boot.yml

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Verify Operator Boot (Issue #146)
1+
name: "Verify Operator Boot (Issue #146)"
22

33
# Verifies that the operator binary builds and connects to a live kind cluster.
44
# Acceptance criteria:
@@ -29,45 +29,73 @@ jobs:
2929
# ── 1. Checkout ──────────────────────────────────────────────────────────
3030
- uses: actions/checkout@v4
3131

32+
- name: Decide whether boot verification should run
33+
id: scope
34+
run: |
35+
set -euo pipefail
36+
if [[ "${{ github.event_name }}" != "pull_request" ]]; then
37+
echo "run=true" >> "$GITHUB_OUTPUT"
38+
exit 0
39+
fi
40+
41+
BASE_SHA="${{ github.event.pull_request.base.sha }}"
42+
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
43+
CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA" || true)
44+
echo "$CHANGED_FILES"
45+
46+
if echo "$CHANGED_FILES" | grep -Eq '^(src/|config/crd/|Cargo\.toml|Cargo\.lock|build\.rs|Makefile)'; then
47+
echo "run=true" >> "$GITHUB_OUTPUT"
48+
else
49+
echo "run=false" >> "$GITHUB_OUTPUT"
50+
fi
51+
3252
# ── 2. Rust toolchain + cache ────────────────────────────────────────────
3353
- name: Install Rust toolchain
54+
if: steps.scope.outputs.run == 'true'
3455
uses: dtolnay/rust-toolchain@stable
3556

3657
- name: Setup Rust cache
58+
if: steps.scope.outputs.run == 'true'
3759
uses: Swatinem/rust-cache@v2
3860
with:
3961
shared-key: "verify-boot"
4062

4163
# ── 3. Build release binary (AC #1) ─────────────────────────────────────
4264
- name: Build release binary
65+
if: steps.scope.outputs.run == 'true'
4366
run: cargo build --release --locked --bin stellar-operator
4467

4568
- name: Confirm binary exists
69+
if: steps.scope.outputs.run == 'true'
4670
run: |
4771
ls -lh target/release/stellar-operator
4872
echo "✅ cargo build --release succeeded"
4973
5074
# ── 4. Create kind cluster (AC #2) ──────────────────────────────────────
5175
- name: Install kind
76+
if: steps.scope.outputs.run == 'true'
5277
uses: helm/kind-action@v1.13.0
5378
with:
5479
install_only: true
5580

5681
- name: Create kind cluster
82+
if: steps.scope.outputs.run == 'true'
5783
run: |
5884
kind create cluster --name ${{ env.CLUSTER_NAME }} --wait 60s
5985
kubectl cluster-info --context kind-${{ env.CLUSTER_NAME }}
6086
echo "✅ kind cluster '${{ env.CLUSTER_NAME }}' is ready"
6187
6288
# ── 5. Install CRD ───────────────────────────────────────────────────────
6389
- name: Install StellarNode CRD
90+
if: steps.scope.outputs.run == 'true'
6491
run: |
6592
kubectl apply -f config/crd/stellarnode-crd.yaml
6693
kubectl wait --for condition=established --timeout=30s \
6794
crd/stellarnodes.stellar.org || true
6895
6996
# ── 6. Run operator and verify log line (AC #2 + AC #3) ─────────────────
7097
- name: Run operator and verify cluster connection
98+
if: steps.scope.outputs.run == 'true'
7199
run: |
72100
# Run the operator in the background, capture output
73101
./target/release/stellar-operator run \
@@ -107,7 +135,7 @@ jobs:
107135
108136
# ── 7. Report any runtime errors ────────────────────────────────────────
109137
- name: Report runtime errors
110-
if: always()
138+
if: always() && steps.scope.outputs.run == 'true'
111139
run: |
112140
echo "--- Runtime error check ---"
113141
if grep -iE "error|panic|missing env" /tmp/operator.log 2>/dev/null; then
@@ -118,7 +146,7 @@ jobs:
118146
119147
# ── 8. Upload log as artifact ────────────────────────────────────────────
120148
- name: Upload operator log
121-
if: always()
149+
if: always() && steps.scope.outputs.run == 'true'
122150
uses: actions/upload-artifact@v4
123151
with:
124152
name: operator-boot-log
@@ -127,5 +155,10 @@ jobs:
127155

128156
# ── 9. Cleanup ───────────────────────────────────────────────────────────
129157
- name: Delete kind cluster
130-
if: always()
158+
if: always() && steps.scope.outputs.run == 'true'
131159
run: kind delete cluster --name ${{ env.CLUSTER_NAME }} || true
160+
161+
- name: Skip message
162+
if: steps.scope.outputs.run != 'true'
163+
run: |
164+
echo "Skipping verify-operator-boot: no operator/runtime files changed."

CONTRIBUTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ Please do not delete the template sections. PRs with empty descriptions or unche
117117

118118
- **Formatting**: Always run `cargo fmt` before committing.
119119
- **Linting**: We use Clippy. Ensure `cargo clippy --all-targets --all-features -- -D warnings` passes.
120+
- **Shell scripts**: We lint scripts under `scripts/` with ShellCheck. Run `find scripts -type f -name "*.sh" -print0 | xargs -0 shellcheck -S error` locally.
120121
- **Security**: All dependencies must be audited. We resolve all `RUSTSEC` advisories immediately.
121122
- **Error Handling**: Prefer the `Result<T>` type defined in `src/error.rs` using `thiserror`.
122123

0 commit comments

Comments
 (0)