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
3 changes: 3 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ jobs:
- 'scripts/shellcheck_validate.sh'
modules:
- 'registry/**/modules/**'
templates:
- 'registry/**/templates/**'
shell:
- '**/*.sh'
all:
Expand Down Expand Up @@ -66,6 +68,7 @@ jobs:
ALL_CHANGED_FILES: ${{ steps.filter.outputs.all_files }}
SHARED_CHANGED: ${{ steps.filter.outputs.shared }}
MODULE_CHANGED_FILES: ${{ steps.filter.outputs.modules_files }}
TEMPLATE_CHANGED_FILES: ${{ steps.filter.outputs.templates_files }}
run: bun terraform-validate
- name: Run ShellCheck
env:
Expand Down
29 changes: 22 additions & 7 deletions registry/mavrickrishi/modules/nexus-repository/main.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
import { describe, expect, it } from "bun:test";
import { spawn } from "bun";
import { beforeAll, describe, expect, it } from "bun:test";
import {
executeScriptInContainer,
runTerraformApply,
runTerraformInit,
testRequiredVariables,
} from "~test";

// Image used by every container-based test below. Pulling it the first time a
// test runs can exceed the per-test timeout, so pre-pull it once up front.
const TEST_IMAGE = "ubuntu:20.04";

describe("nexus-repository", async () => {
await runTerraformInit(import.meta.dir);

// Warm the Docker image cache before any container test runs so the one-time
// pull cost isn't charged against (and doesn't time out) the first test.
beforeAll(async () => {
const proc = spawn(["docker", "pull", TEST_IMAGE], {
stdout: "ignore",
stderr: "ignore",
});
await proc.exited;
}, 300_000);

testRequiredVariables(import.meta.dir, {
agent_id: "test-agent",
nexus_url: "https://nexus.example.com",
Expand All @@ -25,7 +40,7 @@ describe("nexus-repository", async () => {
}),
});

const output = await executeScriptInContainer(state, "ubuntu:20.04");
const output = await executeScriptInContainer(state, TEST_IMAGE);
expect(output.stdout.join("\n")).toContain("☕ Configuring Maven...");
expect(output.stdout.join("\n")).toContain("🥳 Configuration complete!");
});
Expand All @@ -40,7 +55,7 @@ describe("nexus-repository", async () => {
}),
});

const output = await executeScriptInContainer(state, "ubuntu:20.04");
const output = await executeScriptInContainer(state, TEST_IMAGE);
expect(output.stdout.join("\n")).toContain("📦 Configuring npm...");
expect(output.stdout.join("\n")).toContain("🥳 Configuration complete!");
});
Expand All @@ -55,7 +70,7 @@ describe("nexus-repository", async () => {
}),
});

const output = await executeScriptInContainer(state, "ubuntu:20.04");
const output = await executeScriptInContainer(state, TEST_IMAGE);
expect(output.stdout.join("\n")).toContain("🐍 Configuring pip...");
expect(output.stdout.join("\n")).toContain("🥳 Configuration complete!");
});
Expand All @@ -72,7 +87,7 @@ describe("nexus-repository", async () => {
}),
});

const output = await executeScriptInContainer(state, "ubuntu:20.04");
const output = await executeScriptInContainer(state, TEST_IMAGE);
expect(output.stdout.join("\n")).toContain("☕ Configuring Maven...");
expect(output.stdout.join("\n")).toContain("📦 Configuring npm...");
expect(output.stdout.join("\n")).toContain("🐍 Configuring pip...");
Expand All @@ -89,7 +104,7 @@ describe("nexus-repository", async () => {
package_managers: JSON.stringify({}),
});

const output = await executeScriptInContainer(state, "ubuntu:20.04");
const output = await executeScriptInContainer(state, TEST_IMAGE);
expect(output.stdout.join("\n")).toContain(
"🤔 no maven repository is set, skipping maven configuration.",
);
Expand All @@ -114,7 +129,7 @@ describe("nexus-repository", async () => {
}),
});

const output = await executeScriptInContainer(state, "ubuntu:20.04");
const output = await executeScriptInContainer(state, TEST_IMAGE);
expect(output.stdout.join("\n")).toContain("🐹 Configuring Go...");
expect(output.stdout.join("\n")).toContain(
"Go proxy configured via GOPROXY environment variable",
Expand Down
53 changes: 29 additions & 24 deletions scripts/terraform_validate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

set -euo pipefail

# Auto-detect which Terraform modules to validate based on changed files from paths-filter
# Auto-detect which Terraform modules and templates to validate based on changed
# files from paths-filter.
# Uses paths-filter outputs from GitHub Actions:
# ALL_CHANGED_FILES - all files changed in the PR (for logging)
# SHARED_CHANGED - boolean indicating if shared infrastructure changed
# MODULE_CHANGED_FILES - only files in registry/**/modules/** (for processing)
# Validates all modules if shared infrastructure changes, or skips if no changes detected
# TEMPLATE_CHANGED_FILES - only files in registry/**/templates/** (for processing)
# Validates all modules and templates if shared infrastructure changes, or skips
# if no changes detected.
#
# This script only validates changed modules. Documentation and template changes are ignored.
# This script validates changed modules and templates. Documentation changes are ignored.

# Validates that Terraform variable names use underscores (snake_case) instead
# of hyphens. Hyphens are technically valid but deprecated and non-idiomatic.
Expand All @@ -34,7 +37,7 @@ validate_variable_names() {
found_issues=$((found_issues + 1))
fi
done < <(grep -n 'variable "[^"]*-[^"]*"' "$tf_file" 2> /dev/null || true)
done < <(find "$dir" -name '*.tf' -type f | sort)
done < <(find "$dir" -path '*/.terraform/*' -prune -o -name '*.tf' -type f -print | sort)

return "$found_issues"
}
Expand Down Expand Up @@ -64,48 +67,50 @@ main() {

if [[ "${SHARED_CHANGED:-false}" == "true" ]]; then
echo "==> Shared infrastructure changed"
echo "==> Validating all modules for safety"
echo "==> Validating all modules and templates for safety"
local subdirs
subdirs=$(find "$registry_dir" -mindepth 3 -maxdepth 3 -path "*/modules/*" -type d | sort)
elif [[ -z "${MODULE_CHANGED_FILES:-}" ]]; then
echo "✓ No module files changed, skipping validation"
subdirs=$(find "$registry_dir" -mindepth 3 -maxdepth 3 \( -path "*/modules/*" -o -path "*/templates/*" \) -type d | sort)
elif [[ -z "${MODULE_CHANGED_FILES:-}" ]] && [[ -z "${TEMPLATE_CHANGED_FILES:-}" ]]; then
echo "✓ No module or template files changed, skipping validation"
exit 0
else
CHANGED_FILES=$(echo "$MODULE_CHANGED_FILES" | tr ' ' '\n')
CHANGED_FILES=$(echo "${MODULE_CHANGED_FILES:-} ${TEMPLATE_CHANGED_FILES:-}" | tr ' ' '\n')

MODULE_DIRS=()
TF_DIRS=()
while IFS= read -r file; do
if [[ "$file" =~ \.(md|png|jpg|jpeg|svg)$ ]]; then
continue
fi

if [[ "$file" =~ ^registry/([^/]+)/modules/([^/]+)/ ]]; then
if [[ "$file" =~ ^registry/([^/]+)/(modules|templates)/([^/]+)/ ]]; then
local namespace
namespace="${BASH_REMATCH[1]}"
local module
module="${BASH_REMATCH[2]}"
local module_dir
module_dir="registry/${namespace}/modules/${module}"

if [[ -d "$module_dir" ]] && [[ ! " ${MODULE_DIRS[*]} " =~ " $module_dir " ]]; then
MODULE_DIRS+=("$module_dir")
local kind
kind="${BASH_REMATCH[2]}"
local name
name="${BASH_REMATCH[3]}"
local tf_dir
tf_dir="registry/${namespace}/${kind}/${name}"

if [[ -d "$tf_dir" ]] && [[ ! " ${TF_DIRS[*]} " =~ " $tf_dir " ]]; then
TF_DIRS+=("$tf_dir")
fi
fi
done <<< "$CHANGED_FILES"

if [[ ${#MODULE_DIRS[@]} -eq 0 ]]; then
echo "✓ No modules to validate"
echo " (documentation, templates, namespace files, or modules without changes)"
if [[ ${#TF_DIRS[@]} -eq 0 ]]; then
echo "✓ No modules or templates to validate"
echo " (documentation, namespace files, or directories without changes)"
exit 0
fi

echo "==> Validating ${#MODULE_DIRS[@]} changed module(s):"
for dir in "${MODULE_DIRS[@]}"; do
echo "==> Validating ${#TF_DIRS[@]} changed module(s)/template(s):"
for dir in "${TF_DIRS[@]}"; do
echo " - $dir"
done
echo ""

local subdirs="${MODULE_DIRS[*]}"
local subdirs="${TF_DIRS[*]}"
fi

status=0
Expand Down
Loading