|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +set -euo pipefail |
| 4 | +trap cleanup SIGINT SIGTERM ERR EXIT |
| 5 | + |
| 6 | +REQUIRED_TOOLS=(yq jq git tar cloudsmith) |
| 7 | + |
| 8 | +temp_dir=$(mktemp -d) |
| 9 | + |
| 10 | +cleanup() { |
| 11 | + trap - SIGINT SIGTERM ERR EXIT |
| 12 | + if [[ "${no_clean-}" == "yes" ]]; then |
| 13 | + echo -e "\nSkipping cleanup" |
| 14 | + else |
| 15 | + rm -rf "${temp_dir}" |
| 16 | + fi |
| 17 | +} |
| 18 | + |
| 19 | +check_dependencies() { |
| 20 | + local missing_tools=() |
| 21 | + |
| 22 | + for tool in "${REQUIRED_TOOLS[@]}"; do |
| 23 | + if ! command -v "$tool" >/dev/null 2>&1; then |
| 24 | + missing_tools+=("$tool") |
| 25 | + fi |
| 26 | + done |
| 27 | + |
| 28 | + if (( ${#missing_tools[@]} > 0 )); then |
| 29 | + echo "Error: Missing required tools: ${missing_tools[*]}" >&2 |
| 30 | + exit 1 |
| 31 | + fi |
| 32 | +} |
| 33 | + |
| 34 | +show_usage() { |
| 35 | + cat << EOF |
| 36 | +Usage: $(basename "$0") [OPTIONS] |
| 37 | +
|
| 38 | +Release a Terraform module by packaging, publishing, and tagging. |
| 39 | +
|
| 40 | +Options: |
| 41 | + -p, --publish Publish the module to Cloudsmith repository |
| 42 | + -t, --tag-push Create and push a Git tag for the release |
| 43 | + -m, --module-path Path to the module directory (required) |
| 44 | + -n, --no-clean Skip cleanup of temporary files |
| 45 | + -f, --force Force re-publish of the module |
| 46 | + -h, --help Show this help message |
| 47 | +
|
| 48 | +Example: |
| 49 | + $(basename "$0") -m modules/my-module -p -t |
| 50 | +EOF |
| 51 | +} |
| 52 | + |
| 53 | +module_publish=no |
| 54 | +tag_push=no |
| 55 | +module_path="" |
| 56 | +no_clean=no |
| 57 | +force=no |
| 58 | + |
| 59 | +while :; do |
| 60 | + case "${1-}" in |
| 61 | + -h|--help) |
| 62 | + show_usage |
| 63 | + exit 0 |
| 64 | + ;; |
| 65 | + -p|--publish) |
| 66 | + module_publish=yes |
| 67 | + ;; |
| 68 | + -t|--tag-push) |
| 69 | + tag_push=yes |
| 70 | + ;; |
| 71 | + -m|--module-path) |
| 72 | + module_path="${2-}" |
| 73 | + shift |
| 74 | + ;; |
| 75 | + -n|--no-clean) |
| 76 | + no_clean=yes |
| 77 | + ;; |
| 78 | + -f|--force) |
| 79 | + force=yes |
| 80 | + ;; |
| 81 | + *) |
| 82 | + break |
| 83 | + ;; |
| 84 | + esac |
| 85 | + shift |
| 86 | +done |
| 87 | + |
| 88 | +check_dependencies |
| 89 | + |
| 90 | +if [[ -z "$module_path" ]]; then |
| 91 | + echo "Module path is required" |
| 92 | + exit 1 |
| 93 | +fi |
| 94 | + |
| 95 | +if ! [[ -f "$module_path/.module.toml" ]]; then |
| 96 | + echo "Module file not found: $module_path/.module.toml" |
| 97 | + exit 1 |
| 98 | +fi |
| 99 | + |
| 100 | +module_name="$(yq .module.name $module_path/.module.toml)" |
| 101 | +module_version="$(yq .module.version $module_path/.module.toml)" |
| 102 | +module_type="$(yq .module.type $module_path/.module.toml)" |
| 103 | + |
| 104 | +if ! echo "$module_version" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then |
| 105 | + echo "Invalid version format: $module_version (expected: x.y.z)" |
| 106 | + exit 1 |
| 107 | +fi |
| 108 | + |
| 109 | +if [[ "$module_type" != "terraform" ]]; then |
| 110 | + echo "Invalid module type: $module_type (expected: terraform)" |
| 111 | + exit 1 |
| 112 | +fi |
| 113 | + |
| 114 | +echo -e "Checking for existing version: $module_name-$module_version" |
| 115 | +if [[ "$force" == "no" ]]; then |
| 116 | + # Github fetches the repository with a shallow clone, so we need to fetch all tags |
| 117 | + git fetch origin --tags --quiet |
| 118 | + |
| 119 | + # Check if the version tag already exists |
| 120 | + if git tag -l | grep -q $module_name-$module_version; then |
| 121 | + echo "Version tag already exists: $module_name-$module_version" |
| 122 | + echo "Skipping publish" |
| 123 | + exit 0 |
| 124 | + fi |
| 125 | + |
| 126 | + # Check if the version already exists in Cloudsmith |
| 127 | + cs_version=$(cloudsmith list packages elastio/public \ |
| 128 | + --query "$module_name version:$module_version" \ |
| 129 | + -F json 2>/dev/null | \ |
| 130 | + yq -r '.data | length') |
| 131 | + if [[ "$cs_version" != "0" ]]; then |
| 132 | + echo "Published module already exists: $module_name-$module_version" |
| 133 | + echo "Skipping publish" |
| 134 | + exit 0 |
| 135 | + fi |
| 136 | +else |
| 137 | + echo "Force re-publish enabled" |
| 138 | +fi |
| 139 | + |
| 140 | +echo "Packaging $module_name-$module_version" |
| 141 | +package_file="$temp_dir/terraform-${module_name}-${module_version}.tar.gz" |
| 142 | + |
| 143 | +tar \ |
| 144 | + --exclude='.module.toml' \ |
| 145 | + --exclude='.terraform' \ |
| 146 | + --exclude='*.tfstate*' \ |
| 147 | + --exclude='*_override.tf*' \ |
| 148 | + -C $module_path \ |
| 149 | + -czvf "$package_file" . |
| 150 | + |
| 151 | +echo -e "\nPackage created: $package_file" |
| 152 | + |
| 153 | +if [[ "$module_publish" == "yes" ]]; then |
| 154 | + echo -e "\nPublishing $module_name-$module_version" |
| 155 | + force_opt=$( [[ "$force" == "yes" ]] && echo "--republish" || echo "" ) |
| 156 | + cloudsmith push terraform \ |
| 157 | + elastio/public \ |
| 158 | + $force_opt "$package_file" |
| 159 | +else |
| 160 | + echo -e "\nSkipping publish" |
| 161 | +fi |
| 162 | + |
| 163 | +if [[ "$tag_push" == "yes" ]]; then |
| 164 | + echo -e "\nTagging $module_name-$module_version" |
| 165 | + force_opt=$( [[ "$force" == "yes" ]] && echo "--force" || echo "" ) |
| 166 | + git tag -a $force_opt "$module_name-$module_version" -m "Release $module_name $module_version" |
| 167 | + git push origin $force_opt "$module_name-$module_version" |
| 168 | +else |
| 169 | + echo -e "\nSkipping tag push" |
| 170 | +fi |
| 171 | + |
| 172 | +if [[ -n "${GITHUB_STEP_SUMMARY:-}" ]]; then |
| 173 | + { |
| 174 | + echo "### Module: $module_name" |
| 175 | + echo "- Version: $module_version" |
| 176 | + [[ "$module_publish" == "yes" ]] && echo "- Status: Published ✅" |
| 177 | + [[ "$tag_push" == "yes" ]] && echo "- Tag: $module_name-$module_version ✅" |
| 178 | + } >> "$GITHUB_STEP_SUMMARY" |
| 179 | +fi |
0 commit comments