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
2 changes: 1 addition & 1 deletion .github/workflows/reusable--release--build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
TARGETS: ${{ steps.resolver.outputs.targets }}
run: |
set -euo pipefail
dir=$(jq -r --arg service "$SERVICE" 'first(.[] | select(.type == "container") | select(.service == $service)) | .working_directory' <<<"$TARGETS")
dir=$(jq -r 'first(.[] | select(.type == "container")) | .working_directory' <<<"$TARGETS")
if [ -z "$dir" ]; then
echo "::error::No directory found for service '$SERVICE' among the container targets of workflow-config.yaml"
exit 1
Expand Down
38 changes: 0 additions & 38 deletions .github/workflows/reusable--test-terragrunt-release.yaml

This file was deleted.

82 changes: 0 additions & 82 deletions scripts/terragrunt-release/check-release-configs.sh

This file was deleted.

150 changes: 0 additions & 150 deletions scripts/terragrunt-release/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -83,156 +83,6 @@ test_release_targets_rejects_empty_stdin() {
assert_fails bash "${script_dir}/release-targets.sh" </dev/null
}

write_service_release_config() {
local package="$1" component="${2:-${1##*/}}" exclude_paths="${3:-[\"$1/infrastructure/aws/develop\"]}"
mkdir -p "${package}"
cat > "${package}/release-please-config.json" <<JSON
{"packages":{"${package}":{"release-type":"simple","component":"${component}","include-component-in-tag":true,"exclude-paths":${exclude_paths}}}}
JSON
echo "{\"${package}\":\"0.1.0\"}" > "${package}/release-please-manifest.json"
}

terragrunt_candidate() {
local service="$1" root="$2" excluded="${3:-false}" environment="${4:-production}"
jq -nc --arg service "${service}" --arg root "${root}" --arg environment "${environment}" --argjson excluded "${excluded}" '{
target: {
service: $service,
environment: $environment,
stack: "terragrunt",
working_directory: "\($root)/infrastructure/aws/\($environment)",
type: "terragrunt",
aws_region: "ap-northeast-1",
iam_role_plan: "arn:aws:iam::222222222222:role/\($environment)-plan",
iam_role_apply: "arn:aws:iam::222222222222:role/\($environment)-apply"
},
excluded: $excluded,
root: $root
}'
}

write_candidates() {
printf '%s\n' "$@" | jq -sc '.' > candidates.json
}

check_configs() {
git init -q
git add -A
bash "${script_dir}/check-release-configs.sh" candidates.json
}

test_check_configs_accepts_matching_set() {
write_candidates "$(terragrunt_candidate monolith dystopia/monolith)"
write_service_release_config dystopia/monolith
write_service_release_config dystopia/frontend
assert_eq "" "$(check_configs 2>&1)"
}

test_check_configs_rejects_missing_config() {
write_candidates "$(terragrunt_candidate pennyworth system-components/pennyworth)"
assert_fails check_configs
assert_stderr_contains "system-components/pennyworth/release-please-config.json"
}

test_check_configs_rejects_wrong_component() {
write_candidates "$(terragrunt_candidate monolith dystopia/monolith)"
write_service_release_config dystopia/monolith frontend
assert_fails check_configs
assert_stderr_contains "dystopia/monolith: component must be monolith (got 'frontend')"
}

test_check_configs_rejects_manifest_without_package() {
write_candidates "$(terragrunt_candidate monolith dystopia/monolith)"
write_service_release_config dystopia/monolith
echo '{}' > dystopia/monolith/release-please-manifest.json
assert_fails check_configs
assert_stderr_contains "dystopia/monolith/release-please-manifest.json"
rm dystopia/monolith/release-please-manifest.json
assert_fails check_configs
assert_stderr_contains "dystopia/monolith/release-please-manifest.json"
}

test_check_configs_rejects_incomplete_release_env() {
write_candidates "$(terragrunt_candidate monolith dystopia/monolith | jq -c '.target |= with_entries(select(.key | IN("aws_region", "iam_role_plan", "iam_role_apply") | not))')"
write_service_release_config dystopia/monolith
assert_fails check_configs
assert_stderr_contains "dystopia/monolith/infrastructure/aws/production"
assert_stderr_contains "aws_region"
assert_stderr_contains "iam_role_plan"
assert_stderr_contains "iam_role_apply"
}

test_check_configs_skips_incomplete_excluded_env() {
write_candidates "$(terragrunt_candidate monolith dystopia/monolith true | jq -c '.target.aws_region = ""')"
write_service_release_config dystopia/monolith
assert_eq "" "$(check_configs 2>&1)"
}

test_check_configs_requires_config_for_excluded_env() {
write_candidates "$(terragrunt_candidate monolith dystopia/monolith true)"
assert_fails check_configs
assert_stderr_contains "dystopia/monolith/release-please-config.json"
write_service_release_config dystopia/monolith
assert_eq "" "$(check_configs 2>&1)"
}

test_check_configs_ignores_candidates_that_are_not_terragrunt_production() {
write_candidates \
"$(terragrunt_candidate monolith dystopia/monolith false develop)" \
"$(jq -nc '{target: {service: "frontend", stack: "container", working_directory: "dystopia/frontend", type: "container"}, excluded: false, root: "dystopia/frontend"}')" \
"$(terragrunt_candidate pennyworth system-components/pennyworth | jq -c '.target.environment = "staging"')"
assert_eq "" "$(check_configs 2>&1)"
}

test_check_configs_rejects_candidates_that_are_not_an_array() {
echo '' > candidates.json
assert_fails check_configs
assert_stderr_contains "::error::"
echo '{}' > candidates.json
assert_fails check_configs
assert_stderr_contains "::error::"
}

test_check_configs_rejects_missing_candidates_path() {
assert_fails bash "${script_dir}/check-release-configs.sh"
assert_stderr_contains "::error::usage: check-release-configs.sh <candidates_json_path>"
}

test_check_configs_rejects_candidates_that_are_not_objects_with_a_target() {
local candidates
for candidates in '[1]' '[null]' '[{"target":1}]' '[{"root":"dystopia/monolith"}]'; do
echo "${candidates}" > candidates.json
assert_fails check_configs
assert_stderr_contains "::error::"
assert_eq "1" "$(printf '%s\n' "${last_stderr}" | wc -l | tr -d ' ')"
done
}

test_check_configs_ignores_exclude_paths() {
write_candidates "$(terragrunt_candidate monolith dystopia/monolith)"
write_service_release_config dystopia/monolith monolith '["unrelated/path"]'
assert_eq "" "$(check_configs 2>&1)"
jq -c 'del(.packages["dystopia/monolith"]["exclude-paths"])' dystopia/monolith/release-please-config.json > config.tmp
mv config.tmp dystopia/monolith/release-please-config.json
assert_eq "" "$(check_configs 2>&1)"
}

test_check_configs_ignores_untracked_configs() {
write_candidates
write_service_release_config dystopia/frontend
git init -q
git add -A
write_service_release_config node_modules/pkg pkg '[]'
assert_eq "" "$(bash "${script_dir}/check-release-configs.sh" candidates.json 2>&1)"
}

test_check_configs_rejects_duplicate_service() {
write_candidates
write_service_release_config dystopia/monolith
write_service_release_config system-components/monolith
assert_fails check_configs
assert_stderr_contains "component monolith is used by more than one package: dystopia/monolith system-components/monolith"
}

failed=0
for test_name in $(compgen -A function test_); do
fixture="$(mktemp -d "${work_root}/fixture.XXXXXX")"
Expand Down
42 changes: 2 additions & 40 deletions scripts/workflows/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,10 @@ test_release_build_resolves_the_container_directory_with_the_label_resolver() {

work="$(mktemp -d)"
trap "rm -rf '${work}'" EXIT
targets='[{"service":"api","environment":"develop","stack":"terragrunt","working_directory":"terragrunt/api/develop","type":"terragrunt"},{"service":"web","stack":"container","working_directory":"services/web","type":"container"},{"service":"api","stack":"container","working_directory":"services/api","type":"container"}]'
targets='[{"service":"api","environment":"develop","stack":"terragrunt","working_directory":"terragrunt/api/develop","type":"terragrunt"},{"service":"api","stack":"container","working_directory":"services/api","type":"container"}]'
GITHUB_OUTPUT="${work}/output" SERVICE=api TARGETS="${targets}" bash -c "${run}"
assert_eq "working-directory=services/api" "$(cat "${work}/output")"
for targets in "${targets}" '[]'; do
for targets in '[{"service":"billing","environment":"develop","stack":"terragrunt","working_directory":"terragrunt/billing/develop","type":"terragrunt"}]' '[]'; do
status=0
out="$(GITHUB_OUTPUT="${work}/none" SERVICE=billing TARGETS="${targets}" bash -c "${run}")" || status=$?
assert_eq "1" "${status}"
Expand All @@ -170,44 +170,6 @@ test_release_build_resolves_the_container_directory_with_the_label_resolver() {
done
}

test_release_config_check_uses_the_label_resolver() {
local workflow="${workflows_dir}/reusable--test-terragrunt-release.yaml"
local pin_pattern='^panicboat/deploy-actions/label-resolver@[0-9a-f]{40} # v[0-9]+\.[0-9]+\.[0-9]+$'
local steps='.jobs.validate.steps[]'
local pin step run work fixture status stderr
pin="$(grep -o 'panicboat/deploy-actions/label-resolver@.*' "${workflow}")"
[[ "${pin}" =~ ${pin_pattern} ]] || { echo " unpinned: ${pin}" >&2; exit 1; }
assert_eq "$(grep -o 'panicboat/deploy-actions/label-resolver@.*' "${workflows_dir}/reusable--label-base-deploy--resolver.yaml")" "${pin}"
assert_eq '{"contents":"read"}' "$(yq -o=json -I=0 '.jobs.validate.permissions' "${workflow}")"
assert_eq "1" "$(yq "[${steps} | select(.uses == \"actions/checkout@*\" and .with.path == null)] | length" "${workflow}")"

step="$(yq "${steps} | select(.id == \"resolver\")" "${workflow}")"
assert_eq '${{ github.repository }}' "$(yq '.with.repository' <<<"${step}")"
assert_eq 'all' "$(yq '.with.service' <<<"${step}")"
assert_eq 'null' "$(yq '.with.environments' <<<"${step}")"

step="$(yq "${steps} | select(.name == \"Check release-please configs\")" "${workflow}")"
run="$(yq '.run' <<<"${step}")"
assert_eq '${{ steps.resolver.outputs.candidates }}' "$(yq '.env.CANDIDATES' <<<"${step}")"
assert_eq "0" "$(grep -c '\${{' <<<"${run}" || true)"
grep -qF 'check-release-configs.sh' <<<"${run}"

work="$(mktemp -d)"
trap "rm -rf '${work}'" EXIT
fixture="${work}/caller"
mkdir -p "${fixture}/dystopia/monolith" "${work}/temp"
ln -s "${repo_root}" "${fixture}/.shared-workflows"
echo '{"packages":{"dystopia/monolith":{"component":"monolith"}}}' > "${fixture}/dystopia/monolith/release-please-config.json"
echo '{"dystopia/monolith":"0.1.0"}' > "${fixture}/dystopia/monolith/release-please-manifest.json"
git -C "${fixture}" init -q
git -C "${fixture}" add dystopia
(cd "${fixture}" && RUNNER_TEMP="${work}/temp" CANDIDATES='[{"target":{"service":"monolith","environment":"production","stack":"terragrunt","working_directory":"dystopia/monolith/production","type":"terragrunt","aws_region":"ap-northeast-1","iam_role_plan":"p","iam_role_apply":"a"},"excluded":false,"root":"dystopia/monolith"},{"target":{"service":"monolith","environment":"develop","stack":"terragrunt","working_directory":"dystopia/monolith/develop","type":"terragrunt","aws_region":"ap-northeast-1","iam_role_plan":"p","iam_role_apply":"a"},"excluded":false,"root":"dystopia/develop-only"}]' bash -c "${run}")
status=0
stderr="$(cd "${fixture}" && RUNNER_TEMP="${work}/temp" CANDIDATES='[{"target":{"service":"pennyworth","environment":"production","stack":"terragrunt","working_directory":"p/production","type":"terragrunt","aws_region":"r","iam_role_plan":"p","iam_role_apply":"a"},"excluded":true,"root":"system-components/pennyworth"}]' bash -c "${run}" 2>&1 >/dev/null)" || status=$?
assert_eq "1" "${status}"
grep -qF 'system-components/pennyworth/release-please-config.json' <<<"${stderr}" || { echo " stderr does not name the missing config: ${stderr}" >&2; exit 1; }
}

test_kustomize_builder_checks_out_head_ref_only_for_helmfile() {
local resolver="${workflows_dir}/reusable--label-base-deploy--resolver.yaml"
local kustomize_builder="${workflows_dir}/internal--kustomize-builder.yaml"
Expand Down
Loading