Skip to content
Merged
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
82 changes: 82 additions & 0 deletions .github/workflows/packer-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Packer Static Analysis

on:
pull_request:
paths:
- "packer/**"
- ".github/workflows/packer-lint.yml"
push:
branches:
- main
paths:
- "packer/**"
- ".github/workflows/packer-lint.yml"
workflow_dispatch:

jobs:
validate-packer:
name: Validate Packer HCL Files
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Packer
uses: hashicorp/setup-packer@main
with:
version: "latest"

- name: Initialize Packer
run: |
cd packer/base
packer init .
cd ../cassandra
packer init .

- name: Validate base.pkr.hcl
run: |
cd packer/base
packer validate .

- name: Validate cassandra.pkr.hcl
run: |
cd packer/cassandra
packer validate .

shellcheck:
name: Lint Shell Scripts
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Run ShellCheck
uses: ludeeus/action-shellcheck@master
with:
scandir: "./packer"
severity: error
format: gcc

yamllint:
name: Validate YAML Files
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"

- name: Install yamllint
run: pip install yamllint

- name: Run yamllint
run: |
# Check if .yamllint.yml exists, use it; otherwise use default config
if [ -f packer/.yamllint.yml ]; then
yamllint -c packer/.yamllint.yml packer/
else
yamllint packer/
fi
142 changes: 142 additions & 0 deletions .github/workflows/packer-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: Packer Script Testing

on:
pull_request:
paths:
- 'packer/**'
- '.github/workflows/packer-test.yml'
push:
branches:
- main
paths:
- 'packer/**'
- '.github/workflows/packer-test.yml'
workflow_dispatch:

jobs:
test-individual-scripts:
name: Test Individual Scripts
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
script:
- cassandra/install/install_cassandra_easy_stress.sh
- base/install/install_docker.sh
- base/install/install_python.sh
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build test image
run: |
cd packer
docker build -t easy-cass-lab-packer-test .

- name: Test script - ${{ matrix.script }}
run: |
cd packer
./test-script.sh ${{ matrix.script }}

test-changed-scripts:
name: Test Changed Scripts
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build test image
run: |
cd packer
docker build -t easy-cass-lab-packer-test .

- name: Detect and test changed scripts
run: |
cd packer
echo "Detecting changed shell scripts..."

# Get list of changed .sh files
CHANGED_SCRIPTS=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep '^packer/.*\.sh$' | grep -v 'test-script.sh' || true)

if [ -z "$CHANGED_SCRIPTS" ]; then
echo "No shell scripts changed in this PR"
exit 0
fi

echo "Changed scripts:"
echo "$CHANGED_SCRIPTS"

# Test each changed script
EXIT_CODE=0
for script in $CHANGED_SCRIPTS; do
# Remove 'packer/' prefix if present
script_path="${script#packer/}"

# Skip deleted files
if [ ! -f "$script" ]; then
echo "⊘ $script_path was deleted, skipping test"
continue
fi

echo "Testing: $script_path"

if ./test-script.sh "$script_path"; then
echo "✓ $script_path passed"
else
echo "✗ $script_path failed"
EXIT_CODE=1
fi
done

exit $EXIT_CODE

test-base-provisioning:
name: Test Base Provisioning Sequence
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Test base provisioning
run: |
cd packer
docker compose up --exit-code-from test-base test-base

- name: Show logs on failure
if: failure()
run: |
cd packer
docker compose logs test-base

test-cassandra-provisioning:
name: Test Cassandra Provisioning Sequence
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Test cassandra provisioning
run: |
cd packer
docker compose up --exit-code-from test-cassandra test-cassandra

- name: Show logs on failure
if: failure()
run: |
cd packer
docker compose logs test-cassandra
20 changes: 20 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,26 @@ Before pushing code, verify it passes all checks:

**Note**: `ktlintFormat` auto-fixes many violations but can't fix all issues (e.g., line length). Always run `ktlintCheck` after formatting to catch remaining issues.

### Packer Script Testing

Test packer provisioning scripts locally using Docker (no AWS required):

```bash
# Test base provisioning scripts
./gradlew testPackerBase

# Test Cassandra provisioning scripts
./gradlew testPackerCassandra

# Run all packer tests
./gradlew testPacker

# Test a specific script
./gradlew testPackerScript -Pscript=cassandra/install/install_cassandra_easy_stress.sh
```

For more details, see [packer/README.md](packer/README.md) and [packer/TESTING.md](packer/TESTING.md).

## Development Rules

- All tests should pass before committing.
Expand Down
33 changes: 33 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,39 @@ tasks.test {
}
}

// Packer testing tasks
tasks.register<Exec>("testPackerBase") {
group = "Verification"
description = "Test base packer provisioning scripts using Docker"
workingDir = file("packer")
commandLine = listOf("docker", "compose", "up", "--force-recreate", "--exit-code-from", "test-base", "test-base")
}

tasks.register<Exec>("testPackerCassandra") {
group = "Verification"
description = "Test Cassandra packer provisioning scripts using Docker"
workingDir = file("packer")
commandLine = listOf("docker", "compose", "up", "--force-recreate", "--exit-code-from", "test-cassandra", "test-cassandra")
}

tasks.register("testPacker") {
group = "Verification"
description = "Run all packer provisioning tests"
dependsOn("testPackerBase", "testPackerCassandra")
}

tasks.register<Exec>("testPackerScript") {
group = "Verification"
description = "Test a specific packer script (use -Pscript=path/to/script.sh)"
workingDir = file("packer")
doFirst {
val scriptPath =
project.findProperty("script")?.toString()
?: throw GradleException("Please specify script path with -Pscript=path/to/script.sh")
commandLine = listOf("./test-script.sh", scriptPath)
}
}

tasks.register("buildAll") {
group = "Publish"
// dependsOn("buildDeb")
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ resilience4j = "2.2.0"
# Gradle Plugins
shadow = "8.1.1"
versions = "0.53.0"
ktlint = "13.1.0"
ktlint = "14.0.1"
detekt = "1.23.7"
kover = "0.8.3"

Expand Down
24 changes: 24 additions & 0 deletions packer/.shellcheckrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# ShellCheck configuration for packer scripts
# https://github.com/koalaman/shellcheck/wiki/Directive

# Require explicit shell specification at the top of scripts
shell=bash

# Specify the minimum severity level
# error, warning, info, style
severity=warning

# Disabled checks (comma-separated list of codes)
# Uncomment and modify if you need to disable specific checks
# disable=SC2034,SC2086

# Enable all optional checks
enable=all

# Source path for scripts that use 'source' command
# This helps shellcheck find sourced files
# source-path=SCRIPTDIR

# External sources that shellcheck should not complain about
# Useful for sourced files that may not exist in the repo
# external-sources=true
41 changes: 41 additions & 0 deletions packer/.yamllint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---

Check warning on line 1 in packer/.yamllint.yml

View workflow job for this annotation

GitHub Actions / Validate YAML Files

1:1 [document-start] found forbidden document start "---"
# yamllint configuration for packer YAML files
# https://yamllint.readthedocs.io/en/stable/configuration.html

extends: default

rules:
# Line length - allow longer lines for readability
line-length:
max: 120
level: warning

# Indentation - 2 spaces
indentation:
spaces: 2
indent-sequences: true

# Allow empty values
empty-values:
forbid-in-block-mappings: false
forbid-in-flow-mappings: false

# Comments
comments:
min-spaces-from-content: 1

# Document start (---) is optional
document-start:
present: false

# Trailing spaces
trailing-spaces: enable

# Truthy values (yes/no vs true/false)
truthy:
allowed-values: ['true', 'false', 'yes', 'no']
check-keys: false

# Files to ignore
ignore: |
*.json
Loading
Loading