From 7f130f2402493ac0c6ba1fdeb0595b6e64b053d5 Mon Sep 17 00:00:00 2001 From: M Atif Ali Date: Thu, 10 Apr 2025 16:53:57 +0000 Subject: [PATCH 01/31] Add support for separate module versioning - Add check-version.sh script for checking and updating module versions - Update update-version.sh to handle module-specific tags - Add new check-version npm script This change allows tracking module versions separately using tags in the format release/module-name/v1.0.0 and adds tooling to verify README.md versions match the tags. --- check-version.sh | 149 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + update-version.sh | 151 ++++++++++++++++++++++++++++++++-------------- 3 files changed, 256 insertions(+), 45 deletions(-) create mode 100755 check-version.sh diff --git a/check-version.sh b/check-version.sh new file mode 100755 index 00000000..f2e03203 --- /dev/null +++ b/check-version.sh @@ -0,0 +1,149 @@ +#!/usr/bin/env bash + +# This script checks that README.md files have versions that match module-specific +# tags in the format: release/module-name/v1.0.0 +# It can be used in CI to verify versions are correct. +# +# It also supports updating a README with a new version that will be tagged in the future. +# +# Usage: +# ./check-version.sh # Check all modules with changes +# ./check-version.sh module-name # Check only the specified module +# ./check-version.sh --version=1.2.3 module-name # Update module README to version 1.2.3 + +set -euo pipefail + +# Parse arguments +MODULE_NAME="" +NEW_VERSION="" + +for arg in "$@"; do + if [[ "$arg" == --version=* ]]; then + NEW_VERSION="${arg#*=}" + echo "Will update to version: $NEW_VERSION" + elif [[ "$arg" != --* ]]; then + MODULE_NAME="$arg" + echo "Focusing on module: $MODULE_NAME" + fi +done + +# Function to extract version from README.md +extract_readme_version() { + local file="$1" + grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$file" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" +} + +# List directories with changes that are not README.md or test files +if [[ -n "$MODULE_NAME" ]]; then + # If a specific module is provided, only check that directory + if [[ ! -d "$MODULE_NAME" ]]; then + echo "Error: Module directory '$MODULE_NAME' not found." + exit 1 + fi + mapfile -t changed_dirs < <(echo "$MODULE_NAME") +else + # Get the latest tag for the repository + latest_repo_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") + + # Find directories with changes since the latest tag + mapfile -t changed_dirs < <(git diff --name-only "$latest_repo_tag" -- ':!**/README.md' ':!**/*.test.ts' | xargs dirname | grep -v '^\.' | sort -u) + + echo "Directories with changes: ${changed_dirs[*]}" +fi + +EXIT_CODE=0 + +# Iterate over directories and check/update versions in README.md +for dir in "${changed_dirs[@]}"; do + if [[ -f "$dir/README.md" ]]; then + # Get the module name from the directory + module_name=$(basename "$dir") + + # Get version from README.md + readme_version=$(extract_readme_version "$dir/README.md") + + # If a new version was provided, update the README + if [[ -n "$NEW_VERSION" ]]; then + if [[ "$readme_version" == "$NEW_VERSION" ]]; then + echo "Version in $dir/README.md is already set to $NEW_VERSION" + else + echo "Updating version in $dir/README.md from $readme_version to $NEW_VERSION" + + file="$dir/README.md" + tmpfile=$(mktemp /tmp/tempfile.XXXXXX) + awk -v tag="$NEW_VERSION" ' + BEGIN { in_code_block = 0; in_nested_block = 0 } + { + # Detect the start and end of Markdown code blocks. + if ($0 ~ /^```/) { + in_code_block = !in_code_block + # Reset nested block tracking when exiting a code block. + if (!in_code_block) { + in_nested_block = 0 + } + } + + # Handle nested blocks within a code block. + if (in_code_block) { + # Detect the start of a nested block (skipping "module" blocks). + if ($0 ~ /{/ && !($1 == "module" || $1 ~ /^[a-zA-Z0-9_]+$/)) { + in_nested_block++ + } + + # Detect the end of a nested block. + if ($0 ~ /}/ && in_nested_block > 0) { + in_nested_block-- + } + + # Update "version" only if not in a nested block. + if (!in_nested_block && $1 == "version" && $2 == "=") { + sub(/"[^"]*"/, "\"" tag "\"") + } + } + + print + } + ' "$file" > "$tmpfile" && mv "$tmpfile" "$file" + + echo "Remember to tag this release with: git tag release/$module_name/v$NEW_VERSION" + fi + # Skip the version check when updating + continue + fi + + # Check for module-specific tag with format: release/module-name/v1.0.0 + module_tags=$(git tag -l "release/$module_name/v*" | sort -V) + + # Skip modules that don't have module-specific tags + if [[ -z "$module_tags" ]]; then + echo "Skipping $dir: No module-specific tags found" + continue + fi + + # Check if README version matches any of the module's tags + version_found=false + for tag in $module_tags; do + tag_version=$(echo "$tag" | sed 's|release/'"$module_name"'/v||') + if [[ "$readme_version" == "$tag_version" ]]; then + version_found=true + echo "Version in $dir/README.md ($readme_version) matches tag $tag" + break + fi + done + + if [[ "$version_found" == "false" ]]; then + echo "ERROR: Version in $dir/README.md ($readme_version) does not match any existing tag" + echo "Available tags:" + echo "$module_tags" + EXIT_CODE=1 + fi + fi +done + +if [[ $EXIT_CODE -eq 0 ]]; then + echo "All checked modules have valid versions" +else + echo "Some modules have version mismatches - see errors above" +fi + +exit $EXIT_CODE diff --git a/package.json b/package.json index eea421d8..685f1d27 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "fmt": "bun x prettier -w **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt **/*.tf .sample/main.tf", "fmt:ci": "bun x prettier --check **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt -check **/*.tf .sample/main.tf", "lint": "bun run lint.ts && ./terraform_validate.sh", + "check-version": "./check-version.sh", "update-version": "./update-version.sh" }, "devDependencies": { diff --git a/update-version.sh b/update-version.sh index 09547f9c..52b56798 100755 --- a/update-version.sh +++ b/update-version.sh @@ -1,65 +1,126 @@ #!/usr/bin/env bash -# This script increments the version number in the README.md files of all modules -# by 1 patch version. It is intended to be run from the root -# of the repository or by using the `bun update-version` command. +# This script checks and verifies that README.md files have up-to-date versions +# for modules with module-specific tags in the format: release/module-name/v1.0.0 +# It can be used in CI to verify versions are correct or to update versions locally. +# It is intended to be run from the root of the repository or by using the +# `bun update-version` command. set -euo pipefail -current_tag=$(git describe --tags --abbrev=0) +# Check for --check flag to run in verification mode without making changes +CHECK_ONLY=false +if [[ "$*" == *"--check"* ]]; then + CHECK_ONLY=true + echo "Running in check-only mode (no changes will be made)" +fi -# Increment the patch version -LATEST_TAG=$(echo "$current_tag" | sed 's/^v//' | awk -F. '{print $1"."$2"."$3+1}') || exit $? +# Parse other arguments +MODULE_NAME="" +for arg in "$@"; do + if [[ "$arg" != "--check" ]]; then + MODULE_NAME="$arg" + echo "Focusing on module: $MODULE_NAME" + fi +done + +# Function to extract version from README.md +extract_readme_version() { + local file="$1" + grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$file" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" +} # List directories with changes that are not README.md or test files -mapfile -t changed_dirs < <(git diff --name-only "$current_tag" -- ':!**/README.md' ':!**/*.test.ts' | xargs dirname | grep -v '^\.' | sort -u) +if [[ -n "$MODULE_NAME" ]]; then + # If a specific module is provided, only check that directory + if [[ ! -d "$MODULE_NAME" ]]; then + echo "Error: Module directory '$MODULE_NAME' not found." + exit 1 + fi + mapfile -t changed_dirs < <(echo "$MODULE_NAME") +else + # Get the latest tag for the repository + latest_repo_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") + + # Find directories with changes since the latest tag + mapfile -t changed_dirs < <(git diff --name-only "$latest_repo_tag" -- ':!**/README.md' ':!**/*.test.ts' | xargs dirname | grep -v '^\.' | sort -u) + + echo "Directories with changes: ${changed_dirs[*]}" +fi -echo "Directories with changes: ${changed_dirs[*]}" +EXIT_CODE=0 -# Iterate over directories and update version in README.md +# Iterate over directories and check/update versions in README.md for dir in "${changed_dirs[@]}"; do if [[ -f "$dir/README.md" ]]; then - file="$dir/README.md" - tmpfile=$(mktemp /tmp/tempfile.XXXXXX) - awk -v tag="$LATEST_TAG" ' - BEGIN { in_code_block = 0; in_nested_block = 0 } - { - # Detect the start and end of Markdown code blocks. - if ($0 ~ /^```/) { - in_code_block = !in_code_block - # Reset nested block tracking when exiting a code block. - if (!in_code_block) { - in_nested_block = 0 - } - } - - # Handle nested blocks within a code block. - if (in_code_block) { - # Detect the start of a nested block (skipping "module" blocks). - if ($0 ~ /{/ && !($1 == "module" || $1 ~ /^[a-zA-Z0-9_]+$/)) { - in_nested_block++ - } + # Get the module name from the directory + module_name=$(basename "$dir") + + # Check for module-specific tag with format: release/module-name/v1.0.0 + latest_module_tag=$(git tag -l "release/$module_name/v*" | sort -V | tail -n 1) + + # Skip modules that don't have module-specific tags + if [[ -z "$latest_module_tag" ]]; then + echo "Skipping $dir: No module-specific tag found" + continue + fi + + # Extract version number from tag + current_tag_version=$(echo "$latest_module_tag" | sed 's|release/'"$module_name"'/v||') + + # Get version from README.md + readme_version=$(extract_readme_version "$dir/README.md") + + echo "Processing $dir: Tag version=$current_tag_version, README version=$readme_version" + + # Check if README version matches the current tag version + if [[ "$readme_version" != "$current_tag_version" ]]; then + if [[ "$CHECK_ONLY" == "true" ]]; then + echo "ERROR: Version mismatch in $dir/README.md: Expected $current_tag_version, found $readme_version" + EXIT_CODE=1 + else + echo "Updating version in $dir/README.md from $readme_version to $current_tag_version" + + file="$dir/README.md" + tmpfile=$(mktemp /tmp/tempfile.XXXXXX) + awk -v tag="$current_tag_version" ' + BEGIN { in_code_block = 0; in_nested_block = 0 } + { + # Detect the start and end of Markdown code blocks. + if ($0 ~ /^```/) { + in_code_block = !in_code_block + # Reset nested block tracking when exiting a code block. + if (!in_code_block) { + in_nested_block = 0 + } + } - # Detect the end of a nested block. - if ($0 ~ /}/ && in_nested_block > 0) { - in_nested_block-- - } + # Handle nested blocks within a code block. + if (in_code_block) { + # Detect the start of a nested block (skipping "module" blocks). + if ($0 ~ /{/ && !($1 == "module" || $1 ~ /^[a-zA-Z0-9_]+$/)) { + in_nested_block++ + } - # Update "version" only if not in a nested block. - if (!in_nested_block && $1 == "version" && $2 == "=") { - sub(/"[^"]*"/, "\"" tag "\"") - } - } + # Detect the end of a nested block. + if ($0 ~ /}/ && in_nested_block > 0) { + in_nested_block-- + } - print - } - ' "$file" > "$tmpfile" && mv "$tmpfile" "$file" + # Update "version" only if not in a nested block. + if (!in_nested_block && $1 == "version" && $2 == "=") { + sub(/"[^"]*"/, "\"" tag "\"") + } + } - # Check if the README.md file has changed - if ! git diff --quiet -- "$dir/README.md"; then - echo "Bumping version in $dir/README.md from $current_tag to $LATEST_TAG (incremented)" + print + } + ' "$file" > "$tmpfile" && mv "$tmpfile" "$file" + fi else - echo "Version in $dir/README.md is already up to date" + echo "Version in $dir/README.md is already correct ($readme_version)" fi fi done + +exit $EXIT_CODE From b0069e2d0e8174552969d549305c367b34397357 Mon Sep 17 00:00:00 2001 From: M Atif Ali Date: Thu, 10 Apr 2025 16:57:37 +0000 Subject: [PATCH 02/31] Refactor: Combine version scripts into one versatile tool - Replace update-version.sh and check-version.sh with modules-version.sh - Add support for semantic versioning (patch, minor, major) - Add tag creation capability - Improve CLI interface with better help and options - Update package.json scripts for the new tool --- modules-version.sh | 278 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 4 +- update-version.sh | 126 -------------------- 3 files changed, 280 insertions(+), 128 deletions(-) create mode 100755 modules-version.sh delete mode 100755 update-version.sh diff --git a/modules-version.sh b/modules-version.sh new file mode 100755 index 00000000..ba7dbd1d --- /dev/null +++ b/modules-version.sh @@ -0,0 +1,278 @@ +#!/usr/bin/env bash + +# modules-version: A versatile tool for managing module versions in the Coder modules repository +# +# This script handles module versioning with support for module-specific tags in the format: +# release/module-name/v1.0.0 +# +# Features: +# - Check that README.md versions match module tags (CI-friendly) +# - Update module versions automatically or to specified versions +# - Support for module-specific tags and versioning +# - Create tags for new module versions +# +# Usage: +# ./modules-version.sh # Check all modules with changes +# ./modules-version.sh module-name # Check or update a specific module +# ./modules-version.sh --check # Check-only mode (no changes) +# ./modules-version.sh --set-version=1.2.3 module-name # Set specific version +# ./modules-version.sh --bump=patch module-name # Bump patch version (default) +# ./modules-version.sh --bump=minor module-name # Bump minor version +# ./modules-version.sh --bump=major module-name # Bump major version +# ./modules-version.sh --tag module-name # Create git tag after updating + +set -euo pipefail + +# Default values +CHECK_ONLY=false +MODULE_NAME="" +VERSION_ACTION="" +VERSION_TYPE="patch" +NEW_VERSION="" +CREATE_TAG=false +SHOW_HELP=false + +# Function to show usage +show_help() { + cat << EOF +modules-version: A versatile tool for managing module versions + +Usage: + ./modules-version.sh [options] [module-name] + +Options: + --check Check mode - verify versions without making changes + --set-version=X.Y.Z Set version to specific number + --bump=patch|minor|major Bump version (patch is default) + --tag Create git tag after updating version + --help Show this help message + +Examples: + ./modules-version.sh # Check all modules with changes + ./modules-version.sh --check # Check-only mode (CI-friendly) + ./modules-version.sh module-name # Check or update a specific module + ./modules-version.sh --set-version=1.2.3 module-name # Set specific version + ./modules-version.sh --bump=minor --tag module-name # Bump minor version and create tag +EOF + exit 0 +} + +# Parse arguments +for arg in "$@"; do + if [[ "$arg" == "--check" ]]; then + CHECK_ONLY=true + elif [[ "$arg" == "--tag" ]]; then + CREATE_TAG=true + elif [[ "$arg" == "--help" ]]; then + SHOW_HELP=true + elif [[ "$arg" == --set-version=* ]]; then + VERSION_ACTION="set" + NEW_VERSION="${arg#*=}" + elif [[ "$arg" == --bump=* ]]; then + VERSION_ACTION="bump" + VERSION_TYPE="${arg#*=}" + if [[ "$VERSION_TYPE" != "patch" && "$VERSION_TYPE" != "minor" && "$VERSION_TYPE" != "major" ]]; then + echo "Error: Version bump type must be 'patch', 'minor', or 'major'" + exit 1 + fi + elif [[ "$arg" != --* ]]; then + MODULE_NAME="$arg" + fi +done + +# Show help if requested +if [[ "$SHOW_HELP" == "true" ]]; then + show_help +fi + +# Report mode +if [[ "$CHECK_ONLY" == "true" ]]; then + echo "Running in check-only mode (no changes will be made)" +fi + +if [[ -n "$MODULE_NAME" ]]; then + echo "Working with module: $MODULE_NAME" +fi + +if [[ "$VERSION_ACTION" == "set" ]]; then + echo "Will set version to: $NEW_VERSION" +elif [[ "$VERSION_ACTION" == "bump" ]]; then + echo "Will bump $VERSION_TYPE version" +fi + +# Function to extract version from README.md +extract_readme_version() { + local file="$1" + grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$file" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" +} + +# Function to bump version according to semantic versioning +bump_version() { + local version="$1" + local type="$2" + + IFS='.' read -r major minor patch <<< "$version" + + if [[ "$type" == "major" ]]; then + echo "$((major + 1)).0.0" + elif [[ "$type" == "minor" ]]; then + echo "$major.$((minor + 1)).0" + else # Default to patch + echo "$major.$minor.$((patch + 1))" + fi +} + +# Function to update version in README.md +update_version_in_readme() { + local file="$1" + local new_version="$2" + local tmpfile + + tmpfile=$(mktemp /tmp/tempfile.XXXXXX) + awk -v tag="$new_version" ' + BEGIN { in_code_block = 0; in_nested_block = 0 } + { + # Detect the start and end of Markdown code blocks. + if ($0 ~ /^```/) { + in_code_block = !in_code_block + # Reset nested block tracking when exiting a code block. + if (!in_code_block) { + in_nested_block = 0 + } + } + + # Handle nested blocks within a code block. + if (in_code_block) { + # Detect the start of a nested block (skipping "module" blocks). + if ($0 ~ /{/ && !($1 == "module" || $1 ~ /^[a-zA-Z0-9_]+$/)) { + in_nested_block++ + } + + # Detect the end of a nested block. + if ($0 ~ /}/ && in_nested_block > 0) { + in_nested_block-- + } + + # Update "version" only if not in a nested block. + if (!in_nested_block && $1 == "version" && $2 == "=") { + sub(/"[^"]*"/, "\"" tag "\"") + } + } + + print + } + ' "$file" > "$tmpfile" && mv "$tmpfile" "$file" +} + +# List directories with changes that are not README.md or test files +if [[ -n "$MODULE_NAME" ]]; then + # If a specific module is provided, only check that directory + if [[ ! -d "$MODULE_NAME" ]]; then + echo "Error: Module directory '$MODULE_NAME' not found." + exit 1 + fi + mapfile -t changed_dirs < <(echo "$MODULE_NAME") +else + # Get the latest tag for the repository + latest_repo_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") + + # Find directories with changes since the latest tag + mapfile -t changed_dirs < <(git diff --name-only "$latest_repo_tag" -- ':!**/README.md' ':!**/*.test.ts' | xargs dirname | grep -v '^\.' | sort -u) + + echo "Directories with changes: ${changed_dirs[*]}" +fi + +EXIT_CODE=0 + +# Iterate over directories and process versions +for dir in "${changed_dirs[@]}"; do + if [[ -f "$dir/README.md" ]]; then + # Get the module name from the directory + module_name=$(basename "$dir") + + # Get version from README.md + readme_version=$(extract_readme_version "$dir/README.md") + + # Check for module-specific tag with format: release/module-name/v1.0.0 + latest_module_tag=$(git tag -l "release/$module_name/v*" | sort -V | tail -n 1) + if [[ -n "$latest_module_tag" ]]; then + latest_tag_version=$(echo "$latest_module_tag" | sed 's|release/'"$module_name"'/v||') + echo "Module $module_name: Latest tag=$latest_tag_version, README version=$readme_version" + else + echo "Module $module_name: No module-specific tags found, README version=$readme_version" + fi + + # Update version if requested and not in check-only mode + if [[ "$CHECK_ONLY" == "false" && ("$VERSION_ACTION" == "set" || "$VERSION_ACTION" == "bump") ]]; then + # Determine the new version + if [[ "$VERSION_ACTION" == "set" ]]; then + target_version="$NEW_VERSION" + else # bump + # Start with the latest tag version if available, otherwise use README version + base_version="" + if [[ -n "$latest_module_tag" ]]; then + base_version="$latest_tag_version" + else + base_version="$readme_version" + fi + target_version=$(bump_version "$base_version" "$VERSION_TYPE") + fi + + # Update README if needed + if [[ "$readme_version" == "$target_version" ]]; then + echo "Version in $dir/README.md is already set to $target_version" + else + echo "Updating version in $dir/README.md from $readme_version to $target_version" + update_version_in_readme "$dir/README.md" "$target_version" + + # Create tag if requested + if [[ "$CREATE_TAG" == "true" ]]; then + tag_name="release/$module_name/v$target_version" + echo "Creating tag: $tag_name" + git tag "$tag_name" + else + echo "To tag this release, use: git tag release/$module_name/v$target_version" + fi + fi + continue + fi + + # Only do version checking if we're not updating + if [[ "$VERSION_ACTION" != "set" && "$VERSION_ACTION" != "bump" ]]; then + # Get all tags for the module + module_tags=$(git tag -l "release/$module_name/v*" | sort -V) + + # Skip modules that don't have module-specific tags + if [[ -z "$module_tags" ]]; then + echo "Skipping version check for $dir: No module-specific tags found" + continue + fi + + # Check if README version matches any of the module's tags + version_found=false + for tag in $module_tags; do + tag_version=$(echo "$tag" | sed 's|release/'"$module_name"'/v||') + if [[ "$readme_version" == "$tag_version" ]]; then + version_found=true + echo "✅ Version in $dir/README.md ($readme_version) matches tag $tag" + break + fi + done + + if [[ "$version_found" == "false" ]]; then + echo "❌ ERROR: Version in $dir/README.md ($readme_version) does not match any existing tag" + echo "Available tags:" + echo "$module_tags" + EXIT_CODE=1 + fi + fi + fi +done + +if [[ $EXIT_CODE -eq 0 ]]; then + echo "✅ All checked modules have valid versions" +else + echo "❌ Some modules have version mismatches - see errors above" +fi + +exit $EXIT_CODE diff --git a/package.json b/package.json index 685f1d27..b9b67a0f 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "fmt": "bun x prettier -w **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt **/*.tf .sample/main.tf", "fmt:ci": "bun x prettier --check **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt -check **/*.tf .sample/main.tf", "lint": "bun run lint.ts && ./terraform_validate.sh", - "check-version": "./check-version.sh", - "update-version": "./update-version.sh" + "version": "./modules-version.sh", + "version:check": "./modules-version.sh --check" }, "devDependencies": { "bun-types": "^1.1.23", diff --git a/update-version.sh b/update-version.sh deleted file mode 100755 index 52b56798..00000000 --- a/update-version.sh +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env bash - -# This script checks and verifies that README.md files have up-to-date versions -# for modules with module-specific tags in the format: release/module-name/v1.0.0 -# It can be used in CI to verify versions are correct or to update versions locally. -# It is intended to be run from the root of the repository or by using the -# `bun update-version` command. - -set -euo pipefail - -# Check for --check flag to run in verification mode without making changes -CHECK_ONLY=false -if [[ "$*" == *"--check"* ]]; then - CHECK_ONLY=true - echo "Running in check-only mode (no changes will be made)" -fi - -# Parse other arguments -MODULE_NAME="" -for arg in "$@"; do - if [[ "$arg" != "--check" ]]; then - MODULE_NAME="$arg" - echo "Focusing on module: $MODULE_NAME" - fi -done - -# Function to extract version from README.md -extract_readme_version() { - local file="$1" - grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$file" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" -} - -# List directories with changes that are not README.md or test files -if [[ -n "$MODULE_NAME" ]]; then - # If a specific module is provided, only check that directory - if [[ ! -d "$MODULE_NAME" ]]; then - echo "Error: Module directory '$MODULE_NAME' not found." - exit 1 - fi - mapfile -t changed_dirs < <(echo "$MODULE_NAME") -else - # Get the latest tag for the repository - latest_repo_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") - - # Find directories with changes since the latest tag - mapfile -t changed_dirs < <(git diff --name-only "$latest_repo_tag" -- ':!**/README.md' ':!**/*.test.ts' | xargs dirname | grep -v '^\.' | sort -u) - - echo "Directories with changes: ${changed_dirs[*]}" -fi - -EXIT_CODE=0 - -# Iterate over directories and check/update versions in README.md -for dir in "${changed_dirs[@]}"; do - if [[ -f "$dir/README.md" ]]; then - # Get the module name from the directory - module_name=$(basename "$dir") - - # Check for module-specific tag with format: release/module-name/v1.0.0 - latest_module_tag=$(git tag -l "release/$module_name/v*" | sort -V | tail -n 1) - - # Skip modules that don't have module-specific tags - if [[ -z "$latest_module_tag" ]]; then - echo "Skipping $dir: No module-specific tag found" - continue - fi - - # Extract version number from tag - current_tag_version=$(echo "$latest_module_tag" | sed 's|release/'"$module_name"'/v||') - - # Get version from README.md - readme_version=$(extract_readme_version "$dir/README.md") - - echo "Processing $dir: Tag version=$current_tag_version, README version=$readme_version" - - # Check if README version matches the current tag version - if [[ "$readme_version" != "$current_tag_version" ]]; then - if [[ "$CHECK_ONLY" == "true" ]]; then - echo "ERROR: Version mismatch in $dir/README.md: Expected $current_tag_version, found $readme_version" - EXIT_CODE=1 - else - echo "Updating version in $dir/README.md from $readme_version to $current_tag_version" - - file="$dir/README.md" - tmpfile=$(mktemp /tmp/tempfile.XXXXXX) - awk -v tag="$current_tag_version" ' - BEGIN { in_code_block = 0; in_nested_block = 0 } - { - # Detect the start and end of Markdown code blocks. - if ($0 ~ /^```/) { - in_code_block = !in_code_block - # Reset nested block tracking when exiting a code block. - if (!in_code_block) { - in_nested_block = 0 - } - } - - # Handle nested blocks within a code block. - if (in_code_block) { - # Detect the start of a nested block (skipping "module" blocks). - if ($0 ~ /{/ && !($1 == "module" || $1 ~ /^[a-zA-Z0-9_]+$/)) { - in_nested_block++ - } - - # Detect the end of a nested block. - if ($0 ~ /}/ && in_nested_block > 0) { - in_nested_block-- - } - - # Update "version" only if not in a nested block. - if (!in_nested_block && $1 == "version" && $2 == "=") { - sub(/"[^"]*"/, "\"" tag "\"") - } - } - - print - } - ' "$file" > "$tmpfile" && mv "$tmpfile" "$file" - fi - else - echo "Version in $dir/README.md is already correct ($readme_version)" - fi - fi -done - -exit $EXIT_CODE From 0611ef2bcf0136c94a0a2513fe2a06a916e9ad4b Mon Sep 17 00:00:00 2001 From: M Atif Ali Date: Thu, 10 Apr 2025 17:04:27 +0000 Subject: [PATCH 03/31] Update CI workflow to use new modules-version.sh tool - Replace old version check mechanism with new --check mode - Improve error messaging for version mismatches - Simplify CI configuration --- .github/workflows/ci.yaml | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2de2364c..ae0c6af5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -51,16 +51,13 @@ jobs: uses: crate-ci/typos@v1.17.2 - name: Lint run: bun lint - - name: Check version + - name: Check module versions shell: bash run: | - # check for version changes - ./update-version.sh - # Check if any changes were made in README.md files - if [[ -n "$(git status --porcelain -- '**/README.md')" ]]; then - echo "Version mismatch detected. Please run ./update-version.sh and commit the updated README.md files." - git diff -- '**/README.md' - exit 1 - else - echo "No version mismatch detected. All versions are up to date." - fi + # Run version check in strict mode - will exit with error if any module + # has a version in README.md that doesn't match its tag + echo "Checking module versions..." + ./modules-version.sh --check + + # If any module needs version updates, the check will fail with details + # about which modules need updating and what versions should be used From 2269e586edeca3351b095c11c9b6d73a6e6ade74 Mon Sep 17 00:00:00 2001 From: M Atif Ali Date: Thu, 10 Apr 2025 17:06:34 +0000 Subject: [PATCH 04/31] Improve CI version check for different workflows - Differentiate between PR checks and main branch checks - For PRs: Verify version is incremented but doesn't need to match tags - For main: Verify versions match tags - Add helpful error messages with specific commands to fix issues - Handle modules without tags gracefully --- .github/workflows/ci.yaml | 62 +++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ae0c6af5..88ac011a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -54,10 +54,60 @@ jobs: - name: Check module versions shell: bash run: | - # Run version check in strict mode - will exit with error if any module - # has a version in README.md that doesn't match its tag - echo "Checking module versions..." - ./modules-version.sh --check + # For PRs: Check that modules with changes have their README versions updated + # For merged commits: Check that versions match tags - # If any module needs version updates, the check will fail with details - # about which modules need updating and what versions should be used + # First, identify which modules have changes + echo "Identifying modules with changes..." + CHANGED_MODULES=$(./modules-version.sh | grep "Module " | cut -d: -f1 | sed 's/Module //') + + if [ "${{ github.event_name }}" == "pull_request" ]; then + echo "Pull request detected - checking if versions need updating..." + + # Extract the base branch (usually main) + BASE_BRANCH="${{ github.base_ref }}" + echo "Base branch: $BASE_BRANCH" + + # For each changed module, check if the version in README.md has been incremented + # compared to the latest tag for that module + EXIT_CODE=0 + for module in $CHANGED_MODULES; do + echo "Checking module: $module" + + # Skip modules without tags + if ! git tag -l "release/$module/v*" | grep -q .; then + echo "Module $module has no previous tags, skipping version check" + continue + fi + + # Get latest tag version for this module + LATEST_TAG=$(git tag -l "release/$module/v*" | sort -V | tail -n 1) + TAG_VERSION=$(echo "$LATEST_TAG" | sed "s|release/$module/v||") + + # Extract version from README.md in the PR + README_VERSION=$(grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$module/README.md" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0") + + echo "Module $module - Latest tag: $TAG_VERSION, PR version: $README_VERSION" + + # Compare versions using simple numeric comparison (assumes semantic versioning) + TAG_VERSION_NUM=$(echo "$TAG_VERSION" | sed 's/\.//g') + README_VERSION_NUM=$(echo "$README_VERSION" | sed 's/\.//g') + + if [ "$README_VERSION_NUM" -le "$TAG_VERSION_NUM" ]; then + echo "ERROR: Version in $module/README.md ($README_VERSION) must be greater than the latest tag ($TAG_VERSION)" + echo "Please update the version in $module/README.md using one of these methods:" + echo " - Run: ./modules-version.sh --bump=patch $module" + echo " - Run: ./modules-version.sh --bump=minor $module" + echo " - Run: ./modules-version.sh --bump=major $module" + EXIT_CODE=1 + else + echo "✓ Version in $module/README.md has been properly incremented" + fi + done + + exit $EXIT_CODE + else + # For pushes to main, run the regular check to ensure versions match tags + echo "Push to branch detected - checking versions match tags..." + ./modules-version.sh --check + fi From c6cffc802a88fcd10768f860a1d81f887f38213a Mon Sep 17 00:00:00 2001 From: M Atif Ali Date: Thu, 10 Apr 2025 17:08:02 +0000 Subject: [PATCH 05/31] Simplify CI version checking - Make version check informational only for PRs - Add ability to skip check with [skip-version-check] in commit message - Remove complex logic in favor of simpler workflow - Ensure developers retain control over versioning --- .github/workflows/ci.yaml | 70 +++++++++------------------------------ 1 file changed, 15 insertions(+), 55 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 88ac011a..9b005542 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -54,60 +54,20 @@ jobs: - name: Check module versions shell: bash run: | - # For PRs: Check that modules with changes have their README versions updated - # For merged commits: Check that versions match tags - - # First, identify which modules have changes - echo "Identifying modules with changes..." - CHANGED_MODULES=$(./modules-version.sh | grep "Module " | cut -d: -f1 | sed 's/Module //') - + # Add ability to skip version check with a marker in commit message + if [[ "${{ contains(github.event.head_commit.message || '', '[skip-version-check]') }}" == "true" ]]; then + echo "Version check skipped by commit message" + exit 0 + fi + + # For PRs, just check that the version in README matches what's in modules-version.sh + # This assumes developer has run the script locally to update versions + echo "Checking module versions for changed modules..." + ./modules-version.sh + + # Skip actual checks when in PR if [ "${{ github.event_name }}" == "pull_request" ]; then - echo "Pull request detected - checking if versions need updating..." - - # Extract the base branch (usually main) - BASE_BRANCH="${{ github.base_ref }}" - echo "Base branch: $BASE_BRANCH" - - # For each changed module, check if the version in README.md has been incremented - # compared to the latest tag for that module - EXIT_CODE=0 - for module in $CHANGED_MODULES; do - echo "Checking module: $module" - - # Skip modules without tags - if ! git tag -l "release/$module/v*" | grep -q .; then - echo "Module $module has no previous tags, skipping version check" - continue - fi - - # Get latest tag version for this module - LATEST_TAG=$(git tag -l "release/$module/v*" | sort -V | tail -n 1) - TAG_VERSION=$(echo "$LATEST_TAG" | sed "s|release/$module/v||") - - # Extract version from README.md in the PR - README_VERSION=$(grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$module/README.md" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0") - - echo "Module $module - Latest tag: $TAG_VERSION, PR version: $README_VERSION" - - # Compare versions using simple numeric comparison (assumes semantic versioning) - TAG_VERSION_NUM=$(echo "$TAG_VERSION" | sed 's/\.//g') - README_VERSION_NUM=$(echo "$README_VERSION" | sed 's/\.//g') - - if [ "$README_VERSION_NUM" -le "$TAG_VERSION_NUM" ]; then - echo "ERROR: Version in $module/README.md ($README_VERSION) must be greater than the latest tag ($TAG_VERSION)" - echo "Please update the version in $module/README.md using one of these methods:" - echo " - Run: ./modules-version.sh --bump=patch $module" - echo " - Run: ./modules-version.sh --bump=minor $module" - echo " - Run: ./modules-version.sh --bump=major $module" - EXIT_CODE=1 - else - echo "✓ Version in $module/README.md has been properly incremented" - fi - done - - exit $EXIT_CODE - else - # For pushes to main, run the regular check to ensure versions match tags - echo "Push to branch detected - checking versions match tags..." - ./modules-version.sh --check + echo "Pull request detected - version check is informational only" + echo "Remember to update versions with ./modules-version.sh if needed" + exit 0 fi From 9bc5419b074dbdd1d664a0a744b51ff097f1e989 Mon Sep 17 00:00:00 2001 From: M Atif Ali Date: Thu, 10 Apr 2025 17:08:40 +0000 Subject: [PATCH 06/31] Remove check-version.sh as it's been replaced by modules-version.sh --- check-version.sh | 149 ----------------------------------------------- 1 file changed, 149 deletions(-) delete mode 100755 check-version.sh diff --git a/check-version.sh b/check-version.sh deleted file mode 100755 index f2e03203..00000000 --- a/check-version.sh +++ /dev/null @@ -1,149 +0,0 @@ -#!/usr/bin/env bash - -# This script checks that README.md files have versions that match module-specific -# tags in the format: release/module-name/v1.0.0 -# It can be used in CI to verify versions are correct. -# -# It also supports updating a README with a new version that will be tagged in the future. -# -# Usage: -# ./check-version.sh # Check all modules with changes -# ./check-version.sh module-name # Check only the specified module -# ./check-version.sh --version=1.2.3 module-name # Update module README to version 1.2.3 - -set -euo pipefail - -# Parse arguments -MODULE_NAME="" -NEW_VERSION="" - -for arg in "$@"; do - if [[ "$arg" == --version=* ]]; then - NEW_VERSION="${arg#*=}" - echo "Will update to version: $NEW_VERSION" - elif [[ "$arg" != --* ]]; then - MODULE_NAME="$arg" - echo "Focusing on module: $MODULE_NAME" - fi -done - -# Function to extract version from README.md -extract_readme_version() { - local file="$1" - grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$file" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" -} - -# List directories with changes that are not README.md or test files -if [[ -n "$MODULE_NAME" ]]; then - # If a specific module is provided, only check that directory - if [[ ! -d "$MODULE_NAME" ]]; then - echo "Error: Module directory '$MODULE_NAME' not found." - exit 1 - fi - mapfile -t changed_dirs < <(echo "$MODULE_NAME") -else - # Get the latest tag for the repository - latest_repo_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") - - # Find directories with changes since the latest tag - mapfile -t changed_dirs < <(git diff --name-only "$latest_repo_tag" -- ':!**/README.md' ':!**/*.test.ts' | xargs dirname | grep -v '^\.' | sort -u) - - echo "Directories with changes: ${changed_dirs[*]}" -fi - -EXIT_CODE=0 - -# Iterate over directories and check/update versions in README.md -for dir in "${changed_dirs[@]}"; do - if [[ -f "$dir/README.md" ]]; then - # Get the module name from the directory - module_name=$(basename "$dir") - - # Get version from README.md - readme_version=$(extract_readme_version "$dir/README.md") - - # If a new version was provided, update the README - if [[ -n "$NEW_VERSION" ]]; then - if [[ "$readme_version" == "$NEW_VERSION" ]]; then - echo "Version in $dir/README.md is already set to $NEW_VERSION" - else - echo "Updating version in $dir/README.md from $readme_version to $NEW_VERSION" - - file="$dir/README.md" - tmpfile=$(mktemp /tmp/tempfile.XXXXXX) - awk -v tag="$NEW_VERSION" ' - BEGIN { in_code_block = 0; in_nested_block = 0 } - { - # Detect the start and end of Markdown code blocks. - if ($0 ~ /^```/) { - in_code_block = !in_code_block - # Reset nested block tracking when exiting a code block. - if (!in_code_block) { - in_nested_block = 0 - } - } - - # Handle nested blocks within a code block. - if (in_code_block) { - # Detect the start of a nested block (skipping "module" blocks). - if ($0 ~ /{/ && !($1 == "module" || $1 ~ /^[a-zA-Z0-9_]+$/)) { - in_nested_block++ - } - - # Detect the end of a nested block. - if ($0 ~ /}/ && in_nested_block > 0) { - in_nested_block-- - } - - # Update "version" only if not in a nested block. - if (!in_nested_block && $1 == "version" && $2 == "=") { - sub(/"[^"]*"/, "\"" tag "\"") - } - } - - print - } - ' "$file" > "$tmpfile" && mv "$tmpfile" "$file" - - echo "Remember to tag this release with: git tag release/$module_name/v$NEW_VERSION" - fi - # Skip the version check when updating - continue - fi - - # Check for module-specific tag with format: release/module-name/v1.0.0 - module_tags=$(git tag -l "release/$module_name/v*" | sort -V) - - # Skip modules that don't have module-specific tags - if [[ -z "$module_tags" ]]; then - echo "Skipping $dir: No module-specific tags found" - continue - fi - - # Check if README version matches any of the module's tags - version_found=false - for tag in $module_tags; do - tag_version=$(echo "$tag" | sed 's|release/'"$module_name"'/v||') - if [[ "$readme_version" == "$tag_version" ]]; then - version_found=true - echo "Version in $dir/README.md ($readme_version) matches tag $tag" - break - fi - done - - if [[ "$version_found" == "false" ]]; then - echo "ERROR: Version in $dir/README.md ($readme_version) does not match any existing tag" - echo "Available tags:" - echo "$module_tags" - EXIT_CODE=1 - fi - fi -done - -if [[ $EXIT_CODE -eq 0 ]]; then - echo "All checked modules have valid versions" -else - echo "Some modules have version mismatches - see errors above" -fi - -exit $EXIT_CODE From 9b89ef44be0978911c7bca364bba2b1350b66d17 Mon Sep 17 00:00:00 2001 From: M Atif Ali Date: Thu, 10 Apr 2025 17:11:03 +0000 Subject: [PATCH 07/31] Improve CI workflow for version checks - Split version check into separate steps with clear purposes - Use GitHub context properly for checking PR vs main branch - Add step outputs for better workflow control - Improve messaging with emojis for better readability - Maintain ability to skip checks when needed --- .github/workflows/ci.yaml | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 9b005542..75262ccf 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -51,23 +51,31 @@ jobs: uses: crate-ci/typos@v1.17.2 - name: Lint run: bun lint - - name: Check module versions + # Skip version checks if requested in commit message + - name: Check for version check skip flag + id: check-skip shell: bash run: | - # Add ability to skip version check with a marker in commit message if [[ "${{ contains(github.event.head_commit.message || '', '[skip-version-check]') }}" == "true" ]]; then - echo "Version check skipped by commit message" - exit 0 + echo "Skipping version check as requested in commit message" + echo "skip=true" >> $GITHUB_OUTPUT + else + echo "skip=false" >> $GITHUB_OUTPUT fi - # For PRs, just check that the version in README matches what's in modules-version.sh - # This assumes developer has run the script locally to update versions - echo "Checking module versions for changed modules..." + # For pull requests: Display version info but don't enforce + - name: Show module version info (PR) + if: github.event_name == 'pull_request' && steps.check-skip.outputs.skip != 'true' + shell: bash + run: | + echo "📌 Checking module versions for changed modules (informational only)..." ./modules-version.sh + echo "ℹ️ This check is informational only. Remember to update versions with ./modules-version.sh if needed." - # Skip actual checks when in PR - if [ "${{ github.event_name }}" == "pull_request" ]; then - echo "Pull request detected - version check is informational only" - echo "Remember to update versions with ./modules-version.sh if needed" - exit 0 - fi + # For main branch: Enforce version checks + - name: Verify module versions (main branch) + if: github.event_name != 'pull_request' && steps.check-skip.outputs.skip != 'true' + shell: bash + run: | + echo "🔍 Verifying module versions match tags..." + ./modules-version.sh --check From 038ef338bbd5698d2007a6bdd26818c4d105e408 Mon Sep 17 00:00:00 2001 From: M Atif Ali Date: Thu, 10 Apr 2025 17:37:53 +0000 Subject: [PATCH 08/31] Refactor CI workflow for version checks - Remove the ability to skip version checks via commit message - Simplify version check logic to only run on pull requests - Update messaging for clarity and maintain informational checks for changed modules --- .github/workflows/ci.yaml | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 75262ccf..627f8ebe 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -51,31 +51,12 @@ jobs: uses: crate-ci/typos@v1.17.2 - name: Lint run: bun lint - # Skip version checks if requested in commit message - - name: Check for version check skip flag - id: check-skip - shell: bash - run: | - if [[ "${{ contains(github.event.head_commit.message || '', '[skip-version-check]') }}" == "true" ]]; then - echo "Skipping version check as requested in commit message" - echo "skip=true" >> $GITHUB_OUTPUT - else - echo "skip=false" >> $GITHUB_OUTPUT - fi - # For pull requests: Display version info but don't enforce - - name: Show module version info (PR) - if: github.event_name == 'pull_request' && steps.check-skip.outputs.skip != 'true' + # Only run version checks on PRs + - name: Verify module versions + if: github.event_name == 'pull_request' shell: bash run: | - echo "📌 Checking module versions for changed modules (informational only)..." + echo "📌 Checking module versions for changed modules..." ./modules-version.sh - echo "ℹ️ This check is informational only. Remember to update versions with ./modules-version.sh if needed." - - # For main branch: Enforce version checks - - name: Verify module versions (main branch) - if: github.event_name != 'pull_request' && steps.check-skip.outputs.skip != 'true' - shell: bash - run: | - echo "🔍 Verifying module versions match tags..." - ./modules-version.sh --check + echo "ℹ️ Remember to update versions with ./modules-version.sh if needed." From 0b7a60234cb31cf82b09b8536974dfce109d08de Mon Sep 17 00:00:00 2001 From: M Atif Ali Date: Thu, 10 Apr 2025 17:43:37 +0000 Subject: [PATCH 09/31] Update CONTRIBUTING.md to clarify release process steps - Streamline the release process instructions for better clarity - Emphasize the importance of creating a PR and updating the README version - Remove outdated steps and consolidate information on automated publishing --- CONTRIBUTING.md | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 60b1260b..9758402e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -56,20 +56,18 @@ module "example" { > [!WARNING] > When creating a new release, make sure that your new version number is fully accurate. If a version number is incorrect or does not exist, we may end up serving incorrect/old data for our various tools and providers. -Much of our release process is automated. To cut a new release: +The release process is automated and follows these steps: -1. Navigate to [GitHub's Releases page](https://github.com/coder/modules/releases) -2. Click "Draft a new release" -3. Click the "Choose a tag" button and type a new release number in the format `v..` (e.g., `v1.18.0`). Then click "Create new tag". -4. Click the "Generate release notes" button, and clean up the resulting README. Be sure to remove any notes that would not be relevant to end-users (e.g., bumping dependencies). -5. Once everything looks good, click the "Publish release" button. +1. Create a PR with your changes +2. Update the version in the module's README.md file with the next version. +3. The CI will automatically check that the version in README.md is updated +4. Once the PR is approved and merged to main: + - The changes will be available on the main branch + - You can then push a new tag for the module from main + - The tag should follow the format: `release/module-name/v1.0.0` -Once the release has been cut, a script will run to check whether there are any modules that will require that the new release number be published to Terraform. If there are any, a new pull request will automatically be generated. Be sure to approve this PR and merge it into the `main` branch. -Following that, our automated processes will handle publishing new data for [`registry.coder.com`](https://github.com/coder/registry.coder.com/): - -1. Publishing new versions to Coder's [Terraform Registry](https://registry.terraform.io/providers/coder/coder/latest) -2. Publishing new data to the [Coder Registry](https://registry.coder.com) +Following that, our automated processes will handle publishing new data to [`registry.coder.com`](https://registry.coder.com): > [!NOTE] > Some data in `registry.coder.com` is fetched on demand from the Module repo's main branch. This data should be updated almost immediately after a new release, but other changes will take some time to propagate. From 7d481e851253e0397fef984763daa18b38059ebb Mon Sep 17 00:00:00 2001 From: M Atif Ali Date: Thu, 10 Apr 2025 17:47:44 +0000 Subject: [PATCH 10/31] `fmt` --- CONTRIBUTING.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9758402e..7ed03773 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -66,7 +66,6 @@ The release process is automated and follows these steps: - You can then push a new tag for the module from main - The tag should follow the format: `release/module-name/v1.0.0` - Following that, our automated processes will handle publishing new data to [`registry.coder.com`](https://registry.coder.com): > [!NOTE] From d5ecb9844652cba79b3a8a917b96d0ac5447c146 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Mon, 14 Apr 2025 19:19:17 +0000 Subject: [PATCH 11/31] refactor: simplify modules-version script with dry-run and bump-only functionality - Replace --check with --dry-run for clearer functionality - Remove --set-version option to simplify script usage - Keep only --bump=patch|minor|major for version updates - Update CONTRIBUTING.md with clear examples of script usage - Update CI workflow and package.json to use new options --- .github/workflows/ci.yaml | 2 +- CONTRIBUTING.md | 22 +++++++++-- modules-version.sh | 78 ++++++++++++++++++++------------------- package.json | 2 +- 4 files changed, 61 insertions(+), 43 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 627f8ebe..f8dbbd99 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -58,5 +58,5 @@ jobs: shell: bash run: | echo "📌 Checking module versions for changed modules..." - ./modules-version.sh + ./modules-version.sh --dry-run echo "ℹ️ Remember to update versions with ./modules-version.sh if needed." diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7ed03773..20d19274 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -59,12 +59,28 @@ module "example" { The release process is automated and follows these steps: 1. Create a PR with your changes -2. Update the version in the module's README.md file with the next version. +2. Update the version in the module's README.md file with the next version using the modules-version.sh script: + ```shell + # Check what changes are needed + ./modules-version.sh --dry-run module-name + + # Bump the patch version + ./modules-version.sh --bump=patch module-name + + # Bump the minor version + ./modules-version.sh --bump=minor module-name + + # Bump the major version + ./modules-version.sh --bump=major module-name + ``` 3. The CI will automatically check that the version in README.md is updated 4. Once the PR is approved and merged to main: - The changes will be available on the main branch - - You can then push a new tag for the module from main - - The tag should follow the format: `release/module-name/v1.0.0` + - You can then create a tag for the module from main: + ```shell + ./modules-version.sh --bump=patch --tag module-name + ``` + - The tag will follow the format: `release/module-name/v1.0.0` Following that, our automated processes will handle publishing new data to [`registry.coder.com`](https://registry.coder.com): diff --git a/modules-version.sh b/modules-version.sh index ba7dbd1d..f588634f 100755 --- a/modules-version.sh +++ b/modules-version.sh @@ -1,73 +1,67 @@ #!/usr/bin/env bash -# modules-version: A versatile tool for managing module versions in the Coder modules repository +# modules-version: A tool for managing module versions in the Coder modules repository # # This script handles module versioning with support for module-specific tags in the format: # release/module-name/v1.0.0 # # Features: # - Check that README.md versions match module tags (CI-friendly) -# - Update module versions automatically or to specified versions +# - Update module versions by bumping major, minor, or patch versions # - Support for module-specific tags and versioning # - Create tags for new module versions # # Usage: # ./modules-version.sh # Check all modules with changes # ./modules-version.sh module-name # Check or update a specific module -# ./modules-version.sh --check # Check-only mode (no changes) -# ./modules-version.sh --set-version=1.2.3 module-name # Set specific version +# ./modules-version.sh --dry-run # Simulate updates without making changes # ./modules-version.sh --bump=patch module-name # Bump patch version (default) # ./modules-version.sh --bump=minor module-name # Bump minor version # ./modules-version.sh --bump=major module-name # Bump major version -# ./modules-version.sh --tag module-name # Create git tag after updating +# ./modules-version.sh --bump=patch --tag module-name # Bump version and create git tag set -euo pipefail # Default values -CHECK_ONLY=false +DRY_RUN=false MODULE_NAME="" VERSION_ACTION="" VERSION_TYPE="patch" -NEW_VERSION="" CREATE_TAG=false SHOW_HELP=false # Function to show usage show_help() { cat << EOF -modules-version: A versatile tool for managing module versions +modules-version: A tool for managing module versions Usage: ./modules-version.sh [options] [module-name] Options: - --check Check mode - verify versions without making changes - --set-version=X.Y.Z Set version to specific number + --dry-run Simulate updates without making changes --bump=patch|minor|major Bump version (patch is default) --tag Create git tag after updating version --help Show this help message Examples: ./modules-version.sh # Check all modules with changes - ./modules-version.sh --check # Check-only mode (CI-friendly) + ./modules-version.sh --dry-run # Show what changes would be made (CI-friendly) ./modules-version.sh module-name # Check or update a specific module - ./modules-version.sh --set-version=1.2.3 module-name # Set specific version - ./modules-version.sh --bump=minor --tag module-name # Bump minor version and create tag + ./modules-version.sh --bump=minor module-name # Bump minor version + ./modules-version.sh --bump=patch --tag module-name # Bump version and create tag EOF exit 0 } # Parse arguments for arg in "$@"; do - if [[ "$arg" == "--check" ]]; then - CHECK_ONLY=true + if [[ "$arg" == "--dry-run" ]]; then + DRY_RUN=true elif [[ "$arg" == "--tag" ]]; then CREATE_TAG=true elif [[ "$arg" == "--help" ]]; then SHOW_HELP=true - elif [[ "$arg" == --set-version=* ]]; then - VERSION_ACTION="set" - NEW_VERSION="${arg#*=}" elif [[ "$arg" == --bump=* ]]; then VERSION_ACTION="bump" VERSION_TYPE="${arg#*=}" @@ -86,17 +80,15 @@ if [[ "$SHOW_HELP" == "true" ]]; then fi # Report mode -if [[ "$CHECK_ONLY" == "true" ]]; then - echo "Running in check-only mode (no changes will be made)" +if [[ "$DRY_RUN" == "true" ]]; then + echo "Running in dry-run mode (no changes will be made)" fi if [[ -n "$MODULE_NAME" ]]; then echo "Working with module: $MODULE_NAME" fi -if [[ "$VERSION_ACTION" == "set" ]]; then - echo "Will set version to: $NEW_VERSION" -elif [[ "$VERSION_ACTION" == "bump" ]]; then +if [[ "$VERSION_ACTION" == "bump" ]]; then echo "Will bump $VERSION_TYPE version" fi @@ -202,21 +194,16 @@ for dir in "${changed_dirs[@]}"; do echo "Module $module_name: No module-specific tags found, README version=$readme_version" fi - # Update version if requested and not in check-only mode - if [[ "$CHECK_ONLY" == "false" && ("$VERSION_ACTION" == "set" || "$VERSION_ACTION" == "bump") ]]; then - # Determine the new version - if [[ "$VERSION_ACTION" == "set" ]]; then - target_version="$NEW_VERSION" - else # bump - # Start with the latest tag version if available, otherwise use README version - base_version="" - if [[ -n "$latest_module_tag" ]]; then - base_version="$latest_tag_version" - else - base_version="$readme_version" - fi - target_version=$(bump_version "$base_version" "$VERSION_TYPE") + # Update version if requested and not in dry-run mode + if [[ "$DRY_RUN" == "false" && "$VERSION_ACTION" == "bump" ]]; then + # Start with the latest tag version if available, otherwise use README version + base_version="" + if [[ -n "$latest_module_tag" ]]; then + base_version="$latest_tag_version" + else + base_version="$readme_version" fi + target_version=$(bump_version "$base_version" "$VERSION_TYPE") # Update README if needed if [[ "$readme_version" == "$target_version" ]]; then @@ -235,10 +222,25 @@ for dir in "${changed_dirs[@]}"; do fi fi continue + elif [[ "$DRY_RUN" == "true" && "$VERSION_ACTION" == "bump" ]]; then + # Show what would happen in dry-run mode + base_version="" + if [[ -n "$latest_module_tag" ]]; then + base_version="$latest_tag_version" + else + base_version="$readme_version" + fi + target_version=$(bump_version "$base_version" "$VERSION_TYPE") + + echo "[DRY RUN] Would update version in $dir/README.md from $readme_version to $target_version" + if [[ "$CREATE_TAG" == "true" ]]; then + echo "[DRY RUN] Would create tag: release/$module_name/v$target_version" + fi + continue fi # Only do version checking if we're not updating - if [[ "$VERSION_ACTION" != "set" && "$VERSION_ACTION" != "bump" ]]; then + if [[ "$VERSION_ACTION" != "bump" ]]; then # Get all tags for the module module_tags=$(git tag -l "release/$module_name/v*" | sort -V) diff --git a/package.json b/package.json index b9b67a0f..6c3838dd 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "fmt:ci": "bun x prettier --check **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt -check **/*.tf .sample/main.tf", "lint": "bun run lint.ts && ./terraform_validate.sh", "version": "./modules-version.sh", - "version:check": "./modules-version.sh --check" + "version:check": "./modules-version.sh --dry-run" }, "devDependencies": { "bun-types": "^1.1.23", From 7c95af8bba65d47de16fa0f8ff3935fe4e42f3c9 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Mon, 14 Apr 2025 19:26:39 +0000 Subject: [PATCH 12/31] chore: implement tag-first workflow with automated PRs - Update versioning workflow to create tags first, then PRs - Use annotated tags with commit messages - Add --auto-pr option to create PRs by github-actions[bot] - Update CONTRIBUTING.md with new workflow examples - Update CI workflow and package.json accordingly --- .github/workflows/ci.yaml | 8 ++--- CONTRIBUTING.md | 36 ++++++++++---------- modules-version.sh | 70 ++++++++++++++++++++++++++++----------- package.json | 5 +-- 4 files changed, 76 insertions(+), 43 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f8dbbd99..4e605966 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -52,11 +52,11 @@ jobs: - name: Lint run: bun lint - # Only run version checks on PRs - - name: Verify module versions + # Verify module tags on PRs + - name: Verify module tags if: github.event_name == 'pull_request' shell: bash run: | - echo "📌 Checking module versions for changed modules..." + echo "📌 Checking module tags for changed modules..." ./modules-version.sh --dry-run - echo "ℹ️ Remember to update versions with ./modules-version.sh if needed." + echo "ℹ️ After merging, create tags with: ./modules-version.sh --tag module-name" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 20d19274..3e394a5f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -59,28 +59,30 @@ module "example" { The release process is automated and follows these steps: 1. Create a PR with your changes -2. Update the version in the module's README.md file with the next version using the modules-version.sh script: +2. The CI will verify that your module works correctly +3. Once the PR is approved and merged to main: + - Create an annotated tag for the module from main: ```shell - # Check what changes are needed - ./modules-version.sh --dry-run module-name + # Create an annotated tag + ./modules-version.sh --tag module-name - # Bump the patch version - ./modules-version.sh --bump=patch module-name - - # Bump the minor version - ./modules-version.sh --bump=minor module-name - - # Bump the major version - ./modules-version.sh --bump=major module-name + # Push the tag to the repository + git push origin release/module-name/vX.Y.Z ``` -3. The CI will automatically check that the version in README.md is updated -4. Once the PR is approved and merged to main: - - The changes will be available on the main branch - - You can then create a tag for the module from main: + - The tag will follow the format: `release/module-name/v1.0.0` + - Alternatively, you can automate creating a PR to update the README version: ```shell - ./modules-version.sh --bump=patch --tag module-name + # Create a tag and automatic PR + ./modules-version.sh --tag --auto-pr module-name + + # Push both the tag and the PR branch + git push origin release/module-name/vX.Y.Z + git push origin auto-update-module-name-vX.Y.Z + + # Create the PR using GitHub CLI + gh pr create --title "chore: update module-name version to X.Y.Z" \ + --body "Automated version update following tag creation." ``` - - The tag will follow the format: `release/module-name/v1.0.0` Following that, our automated processes will handle publishing new data to [`registry.coder.com`](https://registry.coder.com): diff --git a/modules-version.sh b/modules-version.sh index f588634f..97b8e6b9 100755 --- a/modules-version.sh +++ b/modules-version.sh @@ -7,18 +7,19 @@ # # Features: # - Check that README.md versions match module tags (CI-friendly) -# - Update module versions by bumping major, minor, or patch versions +# - Create annotated tags for module releases +# - Create automated PRs to update README versions after tagging # - Support for module-specific tags and versioning -# - Create tags for new module versions # # Usage: -# ./modules-version.sh # Check all modules with changes -# ./modules-version.sh module-name # Check or update a specific module -# ./modules-version.sh --dry-run # Simulate updates without making changes -# ./modules-version.sh --bump=patch module-name # Bump patch version (default) -# ./modules-version.sh --bump=minor module-name # Bump minor version -# ./modules-version.sh --bump=major module-name # Bump major version -# ./modules-version.sh --bump=patch --tag module-name # Bump version and create git tag +# ./modules-version.sh # Check all modules with changes +# ./modules-version.sh module-name # Check a specific module +# ./modules-version.sh --dry-run # Simulate updates without making changes +# ./modules-version.sh --tag module-name # Create annotated git tag +# ./modules-version.sh --tag --auto-pr module-name # Create tag and automated PR to update README +# ./modules-version.sh --bump=patch module-name # Bump patch version (default) +# ./modules-version.sh --bump=minor module-name # Bump minor version +# ./modules-version.sh --bump=major module-name # Bump major version set -euo pipefail @@ -28,6 +29,7 @@ MODULE_NAME="" VERSION_ACTION="" VERSION_TYPE="patch" CREATE_TAG=false +AUTO_PR=false SHOW_HELP=false # Function to show usage @@ -41,15 +43,17 @@ Usage: Options: --dry-run Simulate updates without making changes --bump=patch|minor|major Bump version (patch is default) - --tag Create git tag after updating version + --tag Create annotated git tag + --auto-pr Create automated PR to update README after tagging (used with --tag) --help Show this help message Examples: - ./modules-version.sh # Check all modules with changes - ./modules-version.sh --dry-run # Show what changes would be made (CI-friendly) - ./modules-version.sh module-name # Check or update a specific module - ./modules-version.sh --bump=minor module-name # Bump minor version - ./modules-version.sh --bump=patch --tag module-name # Bump version and create tag + ./modules-version.sh # Check all modules with changes + ./modules-version.sh --dry-run # Show what changes would be made (CI-friendly) + ./modules-version.sh module-name # Check a specific module + ./modules-version.sh --tag module-name # Create annotated tag for a module + ./modules-version.sh --tag --auto-pr module-name # Create tag and automated PR + ./modules-version.sh --bump=minor module-name # Bump minor version in README EOF exit 0 } @@ -60,6 +64,8 @@ for arg in "$@"; do DRY_RUN=true elif [[ "$arg" == "--tag" ]]; then CREATE_TAG=true + elif [[ "$arg" == "--auto-pr" ]]; then + AUTO_PR=true elif [[ "$arg" == "--help" ]]; then SHOW_HELP=true elif [[ "$arg" == --bump=* ]]; then @@ -92,6 +98,14 @@ if [[ "$VERSION_ACTION" == "bump" ]]; then echo "Will bump $VERSION_TYPE version" fi +if [[ "$CREATE_TAG" == "true" ]]; then + echo "Will create annotated tag" + + if [[ "$AUTO_PR" == "true" ]]; then + echo "Will create automated PR to update README" + fi +fi + # Function to extract version from README.md extract_readme_version() { local file="$1" @@ -212,13 +226,25 @@ for dir in "${changed_dirs[@]}"; do echo "Updating version in $dir/README.md from $readme_version to $target_version" update_version_in_readme "$dir/README.md" "$target_version" - # Create tag if requested + # Create annotated tag if requested if [[ "$CREATE_TAG" == "true" ]]; then tag_name="release/$module_name/v$target_version" - echo "Creating tag: $tag_name" - git tag "$tag_name" + echo "Creating annotated tag: $tag_name" + git tag -a "$tag_name" -m "Release $module_name v$target_version" + echo "Remember to push the tag with: git push origin $tag_name" + + # Create automated PR branch for README update if requested + if [[ "$AUTO_PR" == "true" ]]; then + pr_branch="auto-update-$module_name-v$target_version" + echo "Creating branch for automated PR: $pr_branch" + git checkout -b "$pr_branch" + git add "$dir/README.md" + git commit -m "chore: update $module_name version to $target_version" --author="github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>" + echo "Push and create PR with: git push origin $pr_branch && gh pr create --title \"chore: update $module_name version to $target_version\" --body \"Automated version update following tag creation.\"" + git checkout - + fi else - echo "To tag this release, use: git tag release/$module_name/v$target_version" + echo "To tag this release, use: git tag -a release/$module_name/v$target_version -m \"Release $module_name v$target_version\"" fi fi continue @@ -234,7 +260,11 @@ for dir in "${changed_dirs[@]}"; do echo "[DRY RUN] Would update version in $dir/README.md from $readme_version to $target_version" if [[ "$CREATE_TAG" == "true" ]]; then - echo "[DRY RUN] Would create tag: release/$module_name/v$target_version" + echo "[DRY RUN] Would create annotated tag: release/$module_name/v$target_version" + + if [[ "$AUTO_PR" == "true" ]]; then + echo "[DRY RUN] Would create automated PR to update README version to $target_version" + fi fi continue fi diff --git a/package.json b/package.json index 6c3838dd..e91c9b11 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,9 @@ "fmt": "bun x prettier -w **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt **/*.tf .sample/main.tf", "fmt:ci": "bun x prettier --check **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt -check **/*.tf .sample/main.tf", "lint": "bun run lint.ts && ./terraform_validate.sh", - "version": "./modules-version.sh", - "version:check": "./modules-version.sh --dry-run" + "version:tag": "./modules-version.sh --tag", + "version:check": "./modules-version.sh --dry-run", + "version:auto-pr": "./modules-version.sh --tag --auto-pr" }, "devDependencies": { "bun-types": "^1.1.23", From 324a383921c0d699225611c482c35cb493d7f667 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Mon, 14 Apr 2025 19:28:31 +0000 Subject: [PATCH 13/31] feat: implement GitHub Action for automatic README updates when tags are pushed - Create workflow to update README when module tag is pushed - The workflow creates a PR as github-actions[bot] - Simplify module-version.sh to just handle tag creation - Update CONTRIBUTING.md with the new workflow details - Update package.json scripts --- .github/workflows/update-readme-version.yaml | 124 +++++++++++++++++++ CONTRIBUTING.md | 17 +-- modules-version.sh | 29 +---- package.json | 3 +- 4 files changed, 132 insertions(+), 41 deletions(-) create mode 100644 .github/workflows/update-readme-version.yaml diff --git a/.github/workflows/update-readme-version.yaml b/.github/workflows/update-readme-version.yaml new file mode 100644 index 00000000..26f174b8 --- /dev/null +++ b/.github/workflows/update-readme-version.yaml @@ -0,0 +1,124 @@ +name: Update README Version + +on: + push: + tags: + - 'release/*/v*' # Matches tags like release/module-name/v1.0.0 + +jobs: + update-readme: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Need full history for tags + + - name: Set up Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: Install dependencies + run: bun install + + - name: Extract tag information + id: tag + run: | + # Extract module name and version from tag + TAG_NAME="${GITHUB_REF#refs/tags/}" + MODULE_NAME=$(echo $TAG_NAME | cut -d'/' -f2) + VERSION=$(echo $TAG_NAME | cut -d'/' -f3 | sed 's/^v//') + + echo "MODULE_NAME=$MODULE_NAME" >> $GITHUB_OUTPUT + echo "VERSION=$VERSION" >> $GITHUB_OUTPUT + echo "TAG_NAME=$TAG_NAME" >> $GITHUB_OUTPUT + + - name: Check if README needs updating + id: check + run: | + # Check current README version + README_PATH="${{ steps.tag.outputs.MODULE_NAME }}/README.md" + if [ ! -f "$README_PATH" ]; then + echo "README file not found for module ${{ steps.tag.outputs.MODULE_NAME }}" + exit 1 + fi + + # Extract version from README + README_VERSION=$(grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$README_PATH" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+') + + echo "Current README version: $README_VERSION" + echo "Tag version: ${{ steps.tag.outputs.VERSION }}" + + if [ "$README_VERSION" != "${{ steps.tag.outputs.VERSION }}" ]; then + echo "NEEDS_UPDATE=true" >> $GITHUB_OUTPUT + else + echo "NEEDS_UPDATE=false" >> $GITHUB_OUTPUT + fi + + - name: Update README version + if: steps.check.outputs.NEEDS_UPDATE == 'true' + run: | + # Update README with the new version + ./modules-version.sh --bump=patch ${{ steps.tag.outputs.MODULE_NAME }} + + # Modify update_version_in_readme to use the specific version from the tag + TEMP_FILE=$(mktemp) + MODULE_PATH="${{ steps.tag.outputs.MODULE_NAME }}" + README_PATH="$MODULE_PATH/README.md" + + awk -v tag="${{ steps.tag.outputs.VERSION }}" ' + BEGIN { in_code_block = 0; in_nested_block = 0 } + { + # Detect the start and end of Markdown code blocks. + if ($0 ~ /^```/) { + in_code_block = !in_code_block + # Reset nested block tracking when exiting a code block. + if (!in_code_block) { + in_nested_block = 0 + } + } + + # Handle nested blocks within a code block. + if (in_code_block) { + # Detect the start of a nested block (skipping "module" blocks). + if ($0 ~ /{/ && !($1 == "module" || $1 ~ /^[a-zA-Z0-9_]+$/)) { + in_nested_block++ + } + + # Detect the end of a nested block. + if ($0 ~ /}/ && in_nested_block > 0) { + in_nested_block-- + } + + # Update "version" only if not in a nested block. + if (!in_nested_block && $1 == "version" && $2 == "=") { + sub(/"[^"]*"/, "\"" tag "\"") + } + } + + print + } + ' "$README_PATH" > "$TEMP_FILE" && mv "$TEMP_FILE" "$README_PATH" + + echo "Updated README version to ${{ steps.tag.outputs.VERSION }}" + + - name: Create Pull Request + if: steps.check.outputs.NEEDS_UPDATE == 'true' + uses: peter-evans/create-pull-request@v6 + with: + commit-message: "chore: update ${{ steps.tag.outputs.MODULE_NAME }} version to ${{ steps.tag.outputs.VERSION }}" + branch: automated-readme-update-${{ steps.tag.outputs.MODULE_NAME }}-${{ steps.tag.outputs.VERSION }} + base: main + title: "chore: update ${{ steps.tag.outputs.MODULE_NAME }} version to ${{ steps.tag.outputs.VERSION }}" + body: | + This PR automatically updates the README version to match the newly created tag. + + Tag: ${{ steps.tag.outputs.TAG_NAME }} + Module: ${{ steps.tag.outputs.MODULE_NAME }} + Version: ${{ steps.tag.outputs.VERSION }} + delete-branch: true \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3e394a5f..9dc91366 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -70,19 +70,10 @@ The release process is automated and follows these steps: git push origin release/module-name/vX.Y.Z ``` - The tag will follow the format: `release/module-name/v1.0.0` - - Alternatively, you can automate creating a PR to update the README version: - ```shell - # Create a tag and automatic PR - ./modules-version.sh --tag --auto-pr module-name - - # Push both the tag and the PR branch - git push origin release/module-name/vX.Y.Z - git push origin auto-update-module-name-vX.Y.Z - - # Create the PR using GitHub CLI - gh pr create --title "chore: update module-name version to X.Y.Z" \ - --body "Automated version update following tag creation." - ``` + - When you push the tag, a GitHub Action will automatically: + - Create a PR to update the module's README.md version + - The PR will be created by github-actions[bot] + - Once approved, merge the PR to update the README version Following that, our automated processes will handle publishing new data to [`registry.coder.com`](https://registry.coder.com): diff --git a/modules-version.sh b/modules-version.sh index 97b8e6b9..46e8343d 100755 --- a/modules-version.sh +++ b/modules-version.sh @@ -8,7 +8,7 @@ # Features: # - Check that README.md versions match module tags (CI-friendly) # - Create annotated tags for module releases -# - Create automated PRs to update README versions after tagging +# - Bump module versions in README files # - Support for module-specific tags and versioning # # Usage: @@ -16,7 +16,6 @@ # ./modules-version.sh module-name # Check a specific module # ./modules-version.sh --dry-run # Simulate updates without making changes # ./modules-version.sh --tag module-name # Create annotated git tag -# ./modules-version.sh --tag --auto-pr module-name # Create tag and automated PR to update README # ./modules-version.sh --bump=patch module-name # Bump patch version (default) # ./modules-version.sh --bump=minor module-name # Bump minor version # ./modules-version.sh --bump=major module-name # Bump major version @@ -29,7 +28,6 @@ MODULE_NAME="" VERSION_ACTION="" VERSION_TYPE="patch" CREATE_TAG=false -AUTO_PR=false SHOW_HELP=false # Function to show usage @@ -44,7 +42,6 @@ Options: --dry-run Simulate updates without making changes --bump=patch|minor|major Bump version (patch is default) --tag Create annotated git tag - --auto-pr Create automated PR to update README after tagging (used with --tag) --help Show this help message Examples: @@ -52,7 +49,6 @@ Examples: ./modules-version.sh --dry-run # Show what changes would be made (CI-friendly) ./modules-version.sh module-name # Check a specific module ./modules-version.sh --tag module-name # Create annotated tag for a module - ./modules-version.sh --tag --auto-pr module-name # Create tag and automated PR ./modules-version.sh --bump=minor module-name # Bump minor version in README EOF exit 0 @@ -64,8 +60,6 @@ for arg in "$@"; do DRY_RUN=true elif [[ "$arg" == "--tag" ]]; then CREATE_TAG=true - elif [[ "$arg" == "--auto-pr" ]]; then - AUTO_PR=true elif [[ "$arg" == "--help" ]]; then SHOW_HELP=true elif [[ "$arg" == --bump=* ]]; then @@ -100,10 +94,6 @@ fi if [[ "$CREATE_TAG" == "true" ]]; then echo "Will create annotated tag" - - if [[ "$AUTO_PR" == "true" ]]; then - echo "Will create automated PR to update README" - fi fi # Function to extract version from README.md @@ -232,17 +222,7 @@ for dir in "${changed_dirs[@]}"; do echo "Creating annotated tag: $tag_name" git tag -a "$tag_name" -m "Release $module_name v$target_version" echo "Remember to push the tag with: git push origin $tag_name" - - # Create automated PR branch for README update if requested - if [[ "$AUTO_PR" == "true" ]]; then - pr_branch="auto-update-$module_name-v$target_version" - echo "Creating branch for automated PR: $pr_branch" - git checkout -b "$pr_branch" - git add "$dir/README.md" - git commit -m "chore: update $module_name version to $target_version" --author="github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>" - echo "Push and create PR with: git push origin $pr_branch && gh pr create --title \"chore: update $module_name version to $target_version\" --body \"Automated version update following tag creation.\"" - git checkout - - fi + echo "A GitHub Action will automatically create a PR to update README files when the tag is pushed." else echo "To tag this release, use: git tag -a release/$module_name/v$target_version -m \"Release $module_name v$target_version\"" fi @@ -261,10 +241,7 @@ for dir in "${changed_dirs[@]}"; do echo "[DRY RUN] Would update version in $dir/README.md from $readme_version to $target_version" if [[ "$CREATE_TAG" == "true" ]]; then echo "[DRY RUN] Would create annotated tag: release/$module_name/v$target_version" - - if [[ "$AUTO_PR" == "true" ]]; then - echo "[DRY RUN] Would create automated PR to update README version to $target_version" - fi + echo "[DRY RUN] A GitHub Action would create a PR when the tag is pushed" fi continue fi diff --git a/package.json b/package.json index e91c9b11..9c77588c 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,7 @@ "fmt:ci": "bun x prettier --check **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt -check **/*.tf .sample/main.tf", "lint": "bun run lint.ts && ./terraform_validate.sh", "version:tag": "./modules-version.sh --tag", - "version:check": "./modules-version.sh --dry-run", - "version:auto-pr": "./modules-version.sh --tag --auto-pr" + "version:check": "./modules-version.sh --dry-run" }, "devDependencies": { "bun-types": "^1.1.23", From 96657d7120b7f003cfd4ecdc92f4319c335c00f0 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Mon, 14 Apr 2025 19:30:07 +0000 Subject: [PATCH 14/31] feat: add auto-approve and auto-merge for PR workflow - Add auto-approval step using hmarr/auto-approve-action - Enable auto-merge using GitHub CLI - Update CONTRIBUTING.md to reflect fully automated process --- .github/workflows/update-readme-version.yaml | 19 ++++++++++++++++++- CONTRIBUTING.md | 3 ++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.github/workflows/update-readme-version.yaml b/.github/workflows/update-readme-version.yaml index 26f174b8..f3a609a0 100644 --- a/.github/workflows/update-readme-version.yaml +++ b/.github/workflows/update-readme-version.yaml @@ -109,6 +109,7 @@ jobs: - name: Create Pull Request if: steps.check.outputs.NEEDS_UPDATE == 'true' + id: create-pr uses: peter-evans/create-pull-request@v6 with: commit-message: "chore: update ${{ steps.tag.outputs.MODULE_NAME }} version to ${{ steps.tag.outputs.VERSION }}" @@ -121,4 +122,20 @@ jobs: Tag: ${{ steps.tag.outputs.TAG_NAME }} Module: ${{ steps.tag.outputs.MODULE_NAME }} Version: ${{ steps.tag.outputs.VERSION }} - delete-branch: true \ No newline at end of file + + This PR has been automatically approved and enabled for auto-merge. + delete-branch: true + + - name: Auto-approve PR + if: steps.create-pr.outputs.pull-request-number + uses: hmarr/auto-approve-action@v3 + with: + pull-request-number: ${{ steps.create-pr.outputs.pull-request-number }} + + - name: Enable auto-merge + if: steps.create-pr.outputs.pull-request-number + run: | + # Enable auto-merge using GitHub CLI + gh pr merge ${{ steps.create-pr.outputs.pull-request-number }} --auto --squash + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9dc91366..8650c9b0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -73,7 +73,8 @@ The release process is automated and follows these steps: - When you push the tag, a GitHub Action will automatically: - Create a PR to update the module's README.md version - The PR will be created by github-actions[bot] - - Once approved, merge the PR to update the README version + - The PR will be automatically approved and set to auto-merge + - No manual action required - the version will be updated automatically Following that, our automated processes will handle publishing new data to [`registry.coder.com`](https://registry.coder.com): From 1a1dd69a596ac4c0adb2854ee8bb469cd301f500 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Mon, 14 Apr 2025 19:37:46 +0000 Subject: [PATCH 15/31] refactor: reuse modules-version.sh in GitHub Action - Add support for EXACT_VERSION environment variable - Replace bump_version with get_version function - Use existing script in GitHub Action workflow - Minimize code duplication between script and workflow --- .github/workflows/update-readme-version.yaml | 55 +++++--------------- CONTRIBUTING.md | 6 +-- modules-version.sh | 28 ++++++---- 3 files changed, 36 insertions(+), 53 deletions(-) diff --git a/.github/workflows/update-readme-version.yaml b/.github/workflows/update-readme-version.yaml index f3a609a0..e63bedd8 100644 --- a/.github/workflows/update-readme-version.yaml +++ b/.github/workflows/update-readme-version.yaml @@ -1,4 +1,4 @@ -name: Update README Version +name: Auto Update README Version on: push: @@ -63,49 +63,22 @@ jobs: - name: Update README version if: steps.check.outputs.NEEDS_UPDATE == 'true' run: | - # Update README with the new version - ./modules-version.sh --bump=patch ${{ steps.tag.outputs.MODULE_NAME }} + # Use the existing script to update the README version + # We're forcing an exact version (from the tag) instead of bumping - # Modify update_version_in_readme to use the specific version from the tag - TEMP_FILE=$(mktemp) - MODULE_PATH="${{ steps.tag.outputs.MODULE_NAME }}" - README_PATH="$MODULE_PATH/README.md" + # Set git identity for the commit + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - awk -v tag="${{ steps.tag.outputs.VERSION }}" ' - BEGIN { in_code_block = 0; in_nested_block = 0 } - { - # Detect the start and end of Markdown code blocks. - if ($0 ~ /^```/) { - in_code_block = !in_code_block - # Reset nested block tracking when exiting a code block. - if (!in_code_block) { - in_nested_block = 0 - } - } - - # Handle nested blocks within a code block. - if (in_code_block) { - # Detect the start of a nested block (skipping "module" blocks). - if ($0 ~ /{/ && !($1 == "module" || $1 ~ /^[a-zA-Z0-9_]+$/)) { - in_nested_block++ - } - - # Detect the end of a nested block. - if ($0 ~ /}/ && in_nested_block > 0) { - in_nested_block-- - } - - # Update "version" only if not in a nested block. - if (!in_nested_block && $1 == "version" && $2 == "=") { - sub(/"[^"]*"/, "\"" tag "\"") - } - } - - print - } - ' "$README_PATH" > "$TEMP_FILE" && mv "$TEMP_FILE" "$README_PATH" + # Use modules-version.sh to update the README + # This utilizes all the existing logic for finding and updating version strings + VERSION="${{ steps.tag.outputs.VERSION }}" + + # Use a special environment variable to pass the exact version to use + # This avoids having to modify the script + EXACT_VERSION="$VERSION" ./modules-version.sh ${{ steps.tag.outputs.MODULE_NAME }} - echo "Updated README version to ${{ steps.tag.outputs.VERSION }}" + echo "Updated README version to $VERSION" - name: Create Pull Request if: steps.check.outputs.NEEDS_UPDATE == 'true' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8650c9b0..80a5233e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -71,9 +71,9 @@ The release process is automated and follows these steps: ``` - The tag will follow the format: `release/module-name/v1.0.0` - When you push the tag, a GitHub Action will automatically: - - Create a PR to update the module's README.md version - - The PR will be created by github-actions[bot] - - The PR will be automatically approved and set to auto-merge + - Update the module's README.md version using the modules-version.sh script + - Create a PR with the changes by github-actions[bot] + - Auto-approve and set the PR to auto-merge - No manual action required - the version will be updated automatically Following that, our automated processes will handle publishing new data to [`registry.coder.com`](https://registry.coder.com): diff --git a/modules-version.sh b/modules-version.sh index 46e8343d..76847dcb 100755 --- a/modules-version.sh +++ b/modules-version.sh @@ -102,16 +102,26 @@ extract_readme_version() { grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$file" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" } -# Function to bump version according to semantic versioning -bump_version() { - local version="$1" - local type="$2" +# Function to determine version +# Supports: +# 1. Exact version from EXACT_VERSION environment variable +# 2. Bumping version based on type (major, minor, patch) +get_version() { + local current_version="$1" + local bump_type="$2" - IFS='.' read -r major minor patch <<< "$version" + # Check if an exact version is specified via environment variable + if [[ -n "$EXACT_VERSION" ]]; then + echo "$EXACT_VERSION" + return + fi + + # Otherwise bump the version according to semantic versioning + IFS='.' read -r major minor patch <<< "$current_version" - if [[ "$type" == "major" ]]; then + if [[ "$bump_type" == "major" ]]; then echo "$((major + 1)).0.0" - elif [[ "$type" == "minor" ]]; then + elif [[ "$bump_type" == "minor" ]]; then echo "$major.$((minor + 1)).0" else # Default to patch echo "$major.$minor.$((patch + 1))" @@ -207,7 +217,7 @@ for dir in "${changed_dirs[@]}"; do else base_version="$readme_version" fi - target_version=$(bump_version "$base_version" "$VERSION_TYPE") + target_version=$(get_version "$base_version" "$VERSION_TYPE") # Update README if needed if [[ "$readme_version" == "$target_version" ]]; then @@ -236,7 +246,7 @@ for dir in "${changed_dirs[@]}"; do else base_version="$readme_version" fi - target_version=$(bump_version "$base_version" "$VERSION_TYPE") + target_version=$(get_version "$base_version" "$VERSION_TYPE") echo "[DRY RUN] Would update version in $dir/README.md from $readme_version to $target_version" if [[ "$CREATE_TAG" == "true" ]]; then From 4dbe9489bf6d692ff7081cbcad0f77a1c28965ce Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Mon, 14 Apr 2025 19:48:51 +0000 Subject: [PATCH 16/31] feat: add --version parameter for setting exact versions - Add --version=X.Y.Z parameter to set exact versions - Update get_version to use CLI option, environment variable, or bump logic in priority order - Update GitHub Action to use the new parameter instead of environment variable - Update documentation with examples using the new parameter --- .github/workflows/update-readme-version.yaml | 7 ++--- CONTRIBUTING.md | 5 ++- modules-version.sh | 32 +++++++++++++++++--- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/.github/workflows/update-readme-version.yaml b/.github/workflows/update-readme-version.yaml index e63bedd8..4711ca59 100644 --- a/.github/workflows/update-readme-version.yaml +++ b/.github/workflows/update-readme-version.yaml @@ -70,13 +70,12 @@ jobs: git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - # Use modules-version.sh to update the README + # Use modules-version.sh to update the README with the exact version from the tag # This utilizes all the existing logic for finding and updating version strings VERSION="${{ steps.tag.outputs.VERSION }}" - # Use a special environment variable to pass the exact version to use - # This avoids having to modify the script - EXACT_VERSION="$VERSION" ./modules-version.sh ${{ steps.tag.outputs.MODULE_NAME }} + # Use the --version parameter to set the exact version + ./modules-version.sh --version="$VERSION" ${{ steps.tag.outputs.MODULE_NAME }} echo "Updated README version to $VERSION" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 80a5233e..bca51fa3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -63,9 +63,12 @@ The release process is automated and follows these steps: 3. Once the PR is approved and merged to main: - Create an annotated tag for the module from main: ```shell - # Create an annotated tag + # Create an annotated tag (this will use the version from README) ./modules-version.sh --tag module-name + # Alternatively, specify an exact version: + ./modules-version.sh --tag --version=1.2.3 module-name + # Push the tag to the repository git push origin release/module-name/vX.Y.Z ``` diff --git a/modules-version.sh b/modules-version.sh index 76847dcb..dddb2cee 100755 --- a/modules-version.sh +++ b/modules-version.sh @@ -9,6 +9,7 @@ # - Check that README.md versions match module tags (CI-friendly) # - Create annotated tags for module releases # - Bump module versions in README files +# - Set exact versions in README files # - Support for module-specific tags and versioning # # Usage: @@ -19,6 +20,7 @@ # ./modules-version.sh --bump=patch module-name # Bump patch version (default) # ./modules-version.sh --bump=minor module-name # Bump minor version # ./modules-version.sh --bump=major module-name # Bump major version +# ./modules-version.sh --version=1.2.3 module-name # Set exact version number set -euo pipefail @@ -27,6 +29,7 @@ DRY_RUN=false MODULE_NAME="" VERSION_ACTION="" VERSION_TYPE="patch" +EXACT_VERSION_CLI="" CREATE_TAG=false SHOW_HELP=false @@ -41,6 +44,7 @@ Usage: Options: --dry-run Simulate updates without making changes --bump=patch|minor|major Bump version (patch is default) + --version=X.Y.Z Set an exact version number --tag Create annotated git tag --help Show this help message @@ -50,6 +54,7 @@ Examples: ./modules-version.sh module-name # Check a specific module ./modules-version.sh --tag module-name # Create annotated tag for a module ./modules-version.sh --bump=minor module-name # Bump minor version in README + ./modules-version.sh --version=1.2.3 module-name # Set exact version in README EOF exit 0 } @@ -69,6 +74,14 @@ for arg in "$@"; do echo "Error: Version bump type must be 'patch', 'minor', or 'major'" exit 1 fi + elif [[ "$arg" == --version=* ]]; then + VERSION_ACTION="set" + EXACT_VERSION_CLI="${arg#*=}" + # Validate version format + if ! [[ "$EXACT_VERSION_CLI" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Error: Version must be in format X.Y.Z (e.g., 1.2.3)" + exit 1 + fi elif [[ "$arg" != --* ]]; then MODULE_NAME="$arg" fi @@ -90,6 +103,8 @@ fi if [[ "$VERSION_ACTION" == "bump" ]]; then echo "Will bump $VERSION_TYPE version" +elif [[ "$VERSION_ACTION" == "set" ]]; then + echo "Will set version to $EXACT_VERSION_CLI" fi if [[ "$CREATE_TAG" == "true" ]]; then @@ -104,19 +119,26 @@ extract_readme_version() { # Function to determine version # Supports: -# 1. Exact version from EXACT_VERSION environment variable -# 2. Bumping version based on type (major, minor, patch) +# 1. Exact version from --version command-line option +# 2. Exact version from EXACT_VERSION environment variable +# 3. Bumping version based on type (major, minor, patch) get_version() { local current_version="$1" local bump_type="$2" - # Check if an exact version is specified via environment variable - if [[ -n "$EXACT_VERSION" ]]; then + # Priority 1: Use the command-line --version option if specified + if [[ "$VERSION_ACTION" == "set" && -n "$EXACT_VERSION_CLI" ]]; then + echo "$EXACT_VERSION_CLI" + return + fi + + # Priority 2: Check if an exact version is specified via environment variable + if [[ -n "${EXACT_VERSION:-}" ]]; then echo "$EXACT_VERSION" return fi - # Otherwise bump the version according to semantic versioning + # Priority 3: Bump the version according to semantic versioning IFS='.' read -r major minor patch <<< "$current_version" if [[ "$bump_type" == "major" ]]; then From bd1703bcded0639e38aa9e99a6a80ca1f13229cf Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Mon, 14 Apr 2025 19:57:38 +0000 Subject: [PATCH 17/31] refactor: remove environment variable support - Remove EXACT_VERSION environment variable support - Simplify get_version function to only use command-line arguments - Maintain only two options: --version or --bump --- modules-version.sh | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/modules-version.sh b/modules-version.sh index dddb2cee..4129223b 100755 --- a/modules-version.sh +++ b/modules-version.sh @@ -120,8 +120,7 @@ extract_readme_version() { # Function to determine version # Supports: # 1. Exact version from --version command-line option -# 2. Exact version from EXACT_VERSION environment variable -# 3. Bumping version based on type (major, minor, patch) +# 2. Bumping version based on type (major, minor, patch) get_version() { local current_version="$1" local bump_type="$2" @@ -132,13 +131,7 @@ get_version() { return fi - # Priority 2: Check if an exact version is specified via environment variable - if [[ -n "${EXACT_VERSION:-}" ]]; then - echo "$EXACT_VERSION" - return - fi - - # Priority 3: Bump the version according to semantic versioning + # Priority 2: Bump the version according to semantic versioning IFS='.' read -r major minor patch <<< "$current_version" if [[ "$bump_type" == "major" ]]; then From 6f2fe83a0cfdd63b88a1721c6f59a87e143ad4ca Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Mon, 14 Apr 2025 19:59:52 +0000 Subject: [PATCH 18/31] docs: update release process documentation - Update CONTRIBUTING.md to reflect new tag-first workflow - Clarify that contributors don't need to update README versions manually - Remove version check from CI workflow as it's no longer needed - Update documentation with numbered steps for clarity --- .github/workflows/ci.yaml | 11 +++-------- CONTRIBUTING.md | 30 ++++++++++++++++-------------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4e605966..afb17a37 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -52,11 +52,6 @@ jobs: - name: Lint run: bun lint - # Verify module tags on PRs - - name: Verify module tags - if: github.event_name == 'pull_request' - shell: bash - run: | - echo "📌 Checking module tags for changed modules..." - ./modules-version.sh --dry-run - echo "ℹ️ After merging, create tags with: ./modules-version.sh --tag module-name" + # No need to verify module versions in PRs now + # Version checks will be handled by the maintainer after merging + # And automated PRs will update the README.md files diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bca51fa3..e6b87b5e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -58,26 +58,28 @@ module "example" { The release process is automated and follows these steps: -1. Create a PR with your changes -2. The CI will verify that your module works correctly -3. Once the PR is approved and merged to main: - - Create an annotated tag for the module from main: +1. Create a PR with your module changes + - You **do not** need to update the version number in the README.md file + - Focus on implementing your feature or fix + +2. Have your PR reviewed, approved, and merged to main + +3. After merging to main, a maintainer will: + - Create and push an annotated tag with an appropriate version based on your changes: ```shell - # Create an annotated tag (this will use the version from README) - ./modules-version.sh --tag module-name - - # Alternatively, specify an exact version: + # Create an annotated tag with an exact version number ./modules-version.sh --tag --version=1.2.3 module-name # Push the tag to the repository - git push origin release/module-name/vX.Y.Z + git push origin release/module-name/v1.2.3 ``` - The tag will follow the format: `release/module-name/v1.0.0` - - When you push the tag, a GitHub Action will automatically: - - Update the module's README.md version using the modules-version.sh script - - Create a PR with the changes by github-actions[bot] - - Auto-approve and set the PR to auto-merge - - No manual action required - the version will be updated automatically + +4. When the tag is pushed, a GitHub Action will automatically: + - Update the module's README.md version to match the tag + - Create a PR with the version update by github-actions[bot] + - Auto-approve and auto-merge the version update PR + - No manual action required - the version will be updated automatically Following that, our automated processes will handle publishing new data to [`registry.coder.com`](https://registry.coder.com): From 2998721f896348b80aa0e83538c287916db9160d Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Mon, 14 Apr 2025 20:02:56 +0000 Subject: [PATCH 19/31] feat: split scripts into release.sh and update-version.sh - Create release.sh for maintainers to create tags - Create update-version.sh for README version updates - Update GitHub workflow to use the new scripts - Update CONTRIBUTING.md with new script examples - Add --list option to release.sh to show module versions - Update package.json scripts --- .github/workflows/update-readme-version.yaml | 10 +- CONTRIBUTING.md | 7 +- package.json | 4 +- release.sh | 179 +++++++++++++++++++ update-version.sh | 166 +++++++++++++++++ 5 files changed, 359 insertions(+), 7 deletions(-) create mode 100755 release.sh create mode 100755 update-version.sh diff --git a/.github/workflows/update-readme-version.yaml b/.github/workflows/update-readme-version.yaml index 4711ca59..962f4c91 100644 --- a/.github/workflows/update-readme-version.yaml +++ b/.github/workflows/update-readme-version.yaml @@ -70,12 +70,14 @@ jobs: git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - # Use modules-version.sh to update the README with the exact version from the tag - # This utilizes all the existing logic for finding and updating version strings + # Use update-version.sh to update the README with the exact version from the tag + # This script is specifically designed for this purpose VERSION="${{ steps.tag.outputs.VERSION }}" + MODULE="${{ steps.tag.outputs.MODULE_NAME }}" - # Use the --version parameter to set the exact version - ./modules-version.sh --version="$VERSION" ${{ steps.tag.outputs.MODULE_NAME }} + # Update the version in README.md + chmod +x ./update-version.sh + ./update-version.sh "$MODULE" --version="$VERSION" echo "Updated README version to $VERSION" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e6b87b5e..eee782c7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -68,11 +68,16 @@ The release process is automated and follows these steps: - Create and push an annotated tag with an appropriate version based on your changes: ```shell # Create an annotated tag with an exact version number - ./modules-version.sh --tag --version=1.2.3 module-name + ./release.sh module-name --version=1.2.3 # Push the tag to the repository git push origin release/module-name/v1.2.3 ``` + + - View all modules and their current versions with: + ```shell + ./release.sh --list + ``` - The tag will follow the format: `release/module-name/v1.0.0` 4. When the tag is pushed, a GitHub Action will automatically: diff --git a/package.json b/package.json index 9c77588c..1b18d50d 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "fmt": "bun x prettier -w **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt **/*.tf .sample/main.tf", "fmt:ci": "bun x prettier --check **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt -check **/*.tf .sample/main.tf", "lint": "bun run lint.ts && ./terraform_validate.sh", - "version:tag": "./modules-version.sh --tag", - "version:check": "./modules-version.sh --dry-run" + "release": "./release.sh", + "version:check": "./update-version.sh --check" }, "devDependencies": { "bun-types": "^1.1.23", diff --git a/release.sh b/release.sh new file mode 100755 index 00000000..509aedad --- /dev/null +++ b/release.sh @@ -0,0 +1,179 @@ +#!/usr/bin/env bash +# +# release.sh - Create and manage module releases +# +# This script is intended for maintainers to create and manage releases +# by creating annotated tags with appropriate version numbers. +# +# Usage: +# ./release.sh module-name --version=X.Y.Z # Create a tag with specific version +# ./release.sh --help # Show this help message +# ./release.sh --list # List modules with their latest versions + +set -euo pipefail + +# Default values +MODULE_NAME="" +VERSION="" +CREATE_TAG=true +LIST_MODULES=false +SHOW_HELP=false + +# Function to show usage +show_help() { + cat << EOF +release.sh - Create and manage module releases + +Usage: + ./release.sh [options] module-name + +Options: + --version=X.Y.Z Version number for the new release (required) + --dry-run Show what would happen without making changes + --list List all modules with their latest versions + --help Show this help message + +Examples: + ./release.sh code-server --version=1.2.3 # Create release/code-server/v1.2.3 tag + ./release.sh --list # List all modules and their versions + +Notes: + - This script creates annotated tags that trigger automated README updates + - Tags follow the format: release/module-name/vX.Y.Z + - After creating a tag, you need to push it manually with: + git push origin release/module-name/vX.Y.Z +EOF + exit 0 +} + +# Parse arguments +for arg in "$@"; do + if [[ "$arg" == "--help" ]]; then + SHOW_HELP=true + elif [[ "$arg" == "--list" ]]; then + LIST_MODULES=true + elif [[ "$arg" == --version=* ]]; then + VERSION="${arg#*=}" + # Validate version format + if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Error: Version must be in format X.Y.Z (e.g., 1.2.3)" + exit 1 + fi + elif [[ "$arg" == "--dry-run" ]]; then + CREATE_TAG=false + elif [[ "$arg" != --* ]]; then + MODULE_NAME="$arg" + fi +done + +# Show help if requested +if [[ "$SHOW_HELP" == "true" ]]; then + show_help +fi + +# Function to extract version from README.md +extract_readme_version() { + local file="$1" + grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$file" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" +} + +# Function to list all modules and their latest versions +list_modules() { + echo "Listing all modules and their latest versions:" + echo "--------------------------------------------------" + printf "%-30s %-15s %s\n" "MODULE" "README VERSION" "LATEST TAG" + echo "--------------------------------------------------" + + for dir in */; do + if [[ -d "$dir" && -f "${dir}README.md" && "$dir" != ".git/" ]]; then + # Remove trailing slash + module_name="${dir%/}" + + # Get version from README + readme_version=$(extract_readme_version "${dir}README.md") + + # Get latest tag for this module + latest_tag=$(git tag -l "release/${module_name}/v*" | sort -V | tail -n 1) + if [[ -n "$latest_tag" ]]; then + tag_version=$(echo "$latest_tag" | sed 's|release/'"${module_name}"'/v||') + else + tag_version="none" + fi + + printf "%-30s %-15s %s\n" "$module_name" "$readme_version" "$tag_version" + fi + done + + echo "--------------------------------------------------" + echo "To create a new release: ./release.sh module-name --version=X.Y.Z" + exit 0 +} + +# Show list of modules if requested +if [[ "$LIST_MODULES" == "true" ]]; then + list_modules +fi + +# Validate required parameters +if [[ -z "$MODULE_NAME" ]]; then + echo "Error: Module name is required" + echo "Usage: ./release.sh module-name --version=X.Y.Z" + echo "Run ./release.sh --help for more information" + exit 1 +fi + +if [[ -z "$VERSION" ]]; then + echo "Error: Version is required (--version=X.Y.Z)" + echo "Usage: ./release.sh module-name --version=X.Y.Z" + echo "Run ./release.sh --help for more information" + exit 1 +fi + +# Verify module directory exists +if [[ ! -d "$MODULE_NAME" || ! -f "$MODULE_NAME/README.md" ]]; then + echo "Error: Module directory '$MODULE_NAME' not found or missing README.md" + echo "Available modules:" + for dir in */; do + if [[ -d "$dir" && -f "${dir}README.md" && "$dir" != ".git/" ]]; then + echo " ${dir%/}" + fi + done + exit 1 +fi + +# Get current version from README +README_PATH="$MODULE_NAME/README.md" +README_VERSION=$(extract_readme_version "$README_PATH") + +# Construct tag name +TAG_NAME="release/$MODULE_NAME/v$VERSION" + +# Check if tag already exists +if git rev-parse -q --verify "refs/tags/$TAG_NAME" >/dev/null; then + echo "Error: Tag $TAG_NAME already exists" + exit 1 +fi + +# Report what will happen +echo "Module: $MODULE_NAME" +echo "Current README version: $README_VERSION" +echo "New tag version: $VERSION" +echo "Tag name: $TAG_NAME" + +# Create the tag +if [[ "$CREATE_TAG" == "true" ]]; then + echo "Creating annotated tag..." + git tag -a "$TAG_NAME" -m "Release $MODULE_NAME v$VERSION" + echo -e "\nSuccess! Tag '$TAG_NAME' created." + echo -e "\nTo complete the release:" + echo "1. Push the tag to the repository:" + echo " git push origin $TAG_NAME" + echo "" + echo "2. The GitHub Action will automatically create a PR to update" + echo " the README.md version to match the tag." +else + echo "[DRY RUN] Would create tag: $TAG_NAME" + echo "[DRY RUN] Tag message: Release $MODULE_NAME v$VERSION" +fi + +exit 0 \ No newline at end of file diff --git a/update-version.sh b/update-version.sh new file mode 100755 index 00000000..8e84be6d --- /dev/null +++ b/update-version.sh @@ -0,0 +1,166 @@ +#!/usr/bin/env bash +# +# update-version.sh - Update README.md version to match module tag +# +# This script is primarily used by the GitHub Actions workflow +# to update README versions after a new tag is pushed. +# +# Usage: +# ./update-version.sh module-name --version=X.Y.Z # Update README version +# ./update-version.sh --help # Show help message +# ./update-version.sh --check module-name # Check if README version matches tag + +set -euo pipefail + +# Default values +MODULE_NAME="" +VERSION="" +CHECK_ONLY=false +SHOW_HELP=false + +# Function to show usage +show_help() { + cat << EOF +update-version.sh - Update README.md version to match module tag + +Usage: + ./update-version.sh [options] module-name + +Options: + --version=X.Y.Z Version number to set in README.md + --check Only check if README version matches specified version + --help Show this help message + +Examples: + ./update-version.sh code-server --version=1.2.3 # Update version in code-server README + ./update-version.sh --check code-server --version=1.2.3 # Check if versions match + +Notes: + - This script is primarily used by GitHub Actions + - It updates the version in README.md files to match module tags +EOF + exit 0 +} + +# Parse arguments +for arg in "$@"; do + if [[ "$arg" == "--help" ]]; then + SHOW_HELP=true + elif [[ "$arg" == "--check" ]]; then + CHECK_ONLY=true + elif [[ "$arg" == --version=* ]]; then + VERSION="${arg#*=}" + # Validate version format + if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Error: Version must be in format X.Y.Z (e.g., 1.2.3)" + exit 1 + fi + elif [[ "$arg" != --* ]]; then + MODULE_NAME="$arg" + fi +done + +# Show help if requested +if [[ "$SHOW_HELP" == "true" ]]; then + show_help +fi + +# Function to extract version from README.md +extract_readme_version() { + local file="$1" + grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$file" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" +} + +# Function to update version in README.md +update_version_in_readme() { + local file="$1" + local new_version="$2" + local tmpfile + + tmpfile=$(mktemp /tmp/tempfile.XXXXXX) + awk -v tag="$new_version" ' + BEGIN { in_code_block = 0; in_nested_block = 0 } + { + # Detect the start and end of Markdown code blocks. + if ($0 ~ /^```/) { + in_code_block = !in_code_block + # Reset nested block tracking when exiting a code block. + if (!in_code_block) { + in_nested_block = 0 + } + } + + # Handle nested blocks within a code block. + if (in_code_block) { + # Detect the start of a nested block (skipping "module" blocks). + if ($0 ~ /{/ && !($1 == "module" || $1 ~ /^[a-zA-Z0-9_]+$/)) { + in_nested_block++ + } + + # Detect the end of a nested block. + if ($0 ~ /}/ && in_nested_block > 0) { + in_nested_block-- + } + + # Update "version" only if not in a nested block. + if (!in_nested_block && $1 == "version" && $2 == "=") { + sub(/"[^"]*"/, "\"" tag "\"") + } + } + + print + } + ' "$file" > "$tmpfile" && mv "$tmpfile" "$file" +} + +# Validate required parameters +if [[ -z "$MODULE_NAME" ]]; then + echo "Error: Module name is required" + echo "Usage: ./update-version.sh module-name --version=X.Y.Z" + echo "Run ./update-version.sh --help for more information" + exit 1 +fi + +if [[ -z "$VERSION" ]]; then + echo "Error: Version is required (--version=X.Y.Z)" + echo "Usage: ./update-version.sh module-name --version=X.Y.Z" + echo "Run ./update-version.sh --help for more information" + exit 1 +fi + +# Verify module directory exists +if [[ ! -d "$MODULE_NAME" || ! -f "$MODULE_NAME/README.md" ]]; then + echo "Error: Module directory '$MODULE_NAME' not found or missing README.md" + exit 1 +fi + +# Get current version from README +README_PATH="$MODULE_NAME/README.md" +README_VERSION=$(extract_readme_version "$README_PATH") + +# Report current status +echo "Module: $MODULE_NAME" +echo "Current README version: $README_VERSION" +echo "Target version: $VERSION" + +# In check mode, just report if versions match +if [[ "$CHECK_ONLY" == "true" ]]; then + if [[ "$README_VERSION" == "$VERSION" ]]; then + echo "✅ Version in README.md matches target version: $VERSION" + exit 0 + else + echo "❌ Version mismatch: README.md has $README_VERSION, target is $VERSION" + exit 1 + fi +fi + +# Update README if versions differ +if [[ "$README_VERSION" == "$VERSION" ]]; then + echo "Version in $README_PATH is already set to $VERSION" +else + echo "Updating version in $README_PATH from $README_VERSION to $VERSION" + update_version_in_readme "$README_PATH" "$VERSION" + echo "✅ Successfully updated version to $VERSION" +fi + +exit 0 \ No newline at end of file From d63b332c57e64d7778440c495cd59ded13577244 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Mon, 14 Apr 2025 20:16:15 +0000 Subject: [PATCH 20/31] refactor: simplify scripts and workflows - Simplify update-version.sh to focus on version updates only - Simplify release.sh to only handle tag creation and listing - Remove the old modules-version.sh script - Use update-version.sh --check in the GitHub workflow - Rename functions for better clarity - Remove any --bump functionality as it's not needed --- .github/workflows/update-readme-version.yaml | 25 +- modules-version.sh | 312 ------------------- release.sh | 14 +- update-version.sh | 68 ++-- 4 files changed, 45 insertions(+), 374 deletions(-) delete mode 100755 modules-version.sh diff --git a/.github/workflows/update-readme-version.yaml b/.github/workflows/update-readme-version.yaml index 962f4c91..4f2cfe8a 100644 --- a/.github/workflows/update-readme-version.yaml +++ b/.github/workflows/update-readme-version.yaml @@ -41,23 +41,18 @@ jobs: - name: Check if README needs updating id: check run: | - # Check current README version - README_PATH="${{ steps.tag.outputs.MODULE_NAME }}/README.md" - if [ ! -f "$README_PATH" ]; then - echo "README file not found for module ${{ steps.tag.outputs.MODULE_NAME }}" - exit 1 - fi - - # Extract version from README - README_VERSION=$(grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$README_PATH" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+') - - echo "Current README version: $README_VERSION" - echo "Tag version: ${{ steps.tag.outputs.VERSION }}" + # Use the update-version.sh script in check mode + chmod +x ./update-version.sh + MODULE="${{ steps.tag.outputs.MODULE_NAME }}" + VERSION="${{ steps.tag.outputs.VERSION }}" - if [ "$README_VERSION" != "${{ steps.tag.outputs.VERSION }}" ]; then - echo "NEEDS_UPDATE=true" >> $GITHUB_OUTPUT - else + echo "Checking if README version matches tag version..." + if ./update-version.sh --check "$MODULE" --version="$VERSION"; then + echo "README version already matches tag version" echo "NEEDS_UPDATE=false" >> $GITHUB_OUTPUT + else + echo "README version does not match tag version - update needed" + echo "NEEDS_UPDATE=true" >> $GITHUB_OUTPUT fi - name: Update README version diff --git a/modules-version.sh b/modules-version.sh deleted file mode 100755 index 4129223b..00000000 --- a/modules-version.sh +++ /dev/null @@ -1,312 +0,0 @@ -#!/usr/bin/env bash - -# modules-version: A tool for managing module versions in the Coder modules repository -# -# This script handles module versioning with support for module-specific tags in the format: -# release/module-name/v1.0.0 -# -# Features: -# - Check that README.md versions match module tags (CI-friendly) -# - Create annotated tags for module releases -# - Bump module versions in README files -# - Set exact versions in README files -# - Support for module-specific tags and versioning -# -# Usage: -# ./modules-version.sh # Check all modules with changes -# ./modules-version.sh module-name # Check a specific module -# ./modules-version.sh --dry-run # Simulate updates without making changes -# ./modules-version.sh --tag module-name # Create annotated git tag -# ./modules-version.sh --bump=patch module-name # Bump patch version (default) -# ./modules-version.sh --bump=minor module-name # Bump minor version -# ./modules-version.sh --bump=major module-name # Bump major version -# ./modules-version.sh --version=1.2.3 module-name # Set exact version number - -set -euo pipefail - -# Default values -DRY_RUN=false -MODULE_NAME="" -VERSION_ACTION="" -VERSION_TYPE="patch" -EXACT_VERSION_CLI="" -CREATE_TAG=false -SHOW_HELP=false - -# Function to show usage -show_help() { - cat << EOF -modules-version: A tool for managing module versions - -Usage: - ./modules-version.sh [options] [module-name] - -Options: - --dry-run Simulate updates without making changes - --bump=patch|minor|major Bump version (patch is default) - --version=X.Y.Z Set an exact version number - --tag Create annotated git tag - --help Show this help message - -Examples: - ./modules-version.sh # Check all modules with changes - ./modules-version.sh --dry-run # Show what changes would be made (CI-friendly) - ./modules-version.sh module-name # Check a specific module - ./modules-version.sh --tag module-name # Create annotated tag for a module - ./modules-version.sh --bump=minor module-name # Bump minor version in README - ./modules-version.sh --version=1.2.3 module-name # Set exact version in README -EOF - exit 0 -} - -# Parse arguments -for arg in "$@"; do - if [[ "$arg" == "--dry-run" ]]; then - DRY_RUN=true - elif [[ "$arg" == "--tag" ]]; then - CREATE_TAG=true - elif [[ "$arg" == "--help" ]]; then - SHOW_HELP=true - elif [[ "$arg" == --bump=* ]]; then - VERSION_ACTION="bump" - VERSION_TYPE="${arg#*=}" - if [[ "$VERSION_TYPE" != "patch" && "$VERSION_TYPE" != "minor" && "$VERSION_TYPE" != "major" ]]; then - echo "Error: Version bump type must be 'patch', 'minor', or 'major'" - exit 1 - fi - elif [[ "$arg" == --version=* ]]; then - VERSION_ACTION="set" - EXACT_VERSION_CLI="${arg#*=}" - # Validate version format - if ! [[ "$EXACT_VERSION_CLI" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "Error: Version must be in format X.Y.Z (e.g., 1.2.3)" - exit 1 - fi - elif [[ "$arg" != --* ]]; then - MODULE_NAME="$arg" - fi -done - -# Show help if requested -if [[ "$SHOW_HELP" == "true" ]]; then - show_help -fi - -# Report mode -if [[ "$DRY_RUN" == "true" ]]; then - echo "Running in dry-run mode (no changes will be made)" -fi - -if [[ -n "$MODULE_NAME" ]]; then - echo "Working with module: $MODULE_NAME" -fi - -if [[ "$VERSION_ACTION" == "bump" ]]; then - echo "Will bump $VERSION_TYPE version" -elif [[ "$VERSION_ACTION" == "set" ]]; then - echo "Will set version to $EXACT_VERSION_CLI" -fi - -if [[ "$CREATE_TAG" == "true" ]]; then - echo "Will create annotated tag" -fi - -# Function to extract version from README.md -extract_readme_version() { - local file="$1" - grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$file" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" -} - -# Function to determine version -# Supports: -# 1. Exact version from --version command-line option -# 2. Bumping version based on type (major, minor, patch) -get_version() { - local current_version="$1" - local bump_type="$2" - - # Priority 1: Use the command-line --version option if specified - if [[ "$VERSION_ACTION" == "set" && -n "$EXACT_VERSION_CLI" ]]; then - echo "$EXACT_VERSION_CLI" - return - fi - - # Priority 2: Bump the version according to semantic versioning - IFS='.' read -r major minor patch <<< "$current_version" - - if [[ "$bump_type" == "major" ]]; then - echo "$((major + 1)).0.0" - elif [[ "$bump_type" == "minor" ]]; then - echo "$major.$((minor + 1)).0" - else # Default to patch - echo "$major.$minor.$((patch + 1))" - fi -} - -# Function to update version in README.md -update_version_in_readme() { - local file="$1" - local new_version="$2" - local tmpfile - - tmpfile=$(mktemp /tmp/tempfile.XXXXXX) - awk -v tag="$new_version" ' - BEGIN { in_code_block = 0; in_nested_block = 0 } - { - # Detect the start and end of Markdown code blocks. - if ($0 ~ /^```/) { - in_code_block = !in_code_block - # Reset nested block tracking when exiting a code block. - if (!in_code_block) { - in_nested_block = 0 - } - } - - # Handle nested blocks within a code block. - if (in_code_block) { - # Detect the start of a nested block (skipping "module" blocks). - if ($0 ~ /{/ && !($1 == "module" || $1 ~ /^[a-zA-Z0-9_]+$/)) { - in_nested_block++ - } - - # Detect the end of a nested block. - if ($0 ~ /}/ && in_nested_block > 0) { - in_nested_block-- - } - - # Update "version" only if not in a nested block. - if (!in_nested_block && $1 == "version" && $2 == "=") { - sub(/"[^"]*"/, "\"" tag "\"") - } - } - - print - } - ' "$file" > "$tmpfile" && mv "$tmpfile" "$file" -} - -# List directories with changes that are not README.md or test files -if [[ -n "$MODULE_NAME" ]]; then - # If a specific module is provided, only check that directory - if [[ ! -d "$MODULE_NAME" ]]; then - echo "Error: Module directory '$MODULE_NAME' not found." - exit 1 - fi - mapfile -t changed_dirs < <(echo "$MODULE_NAME") -else - # Get the latest tag for the repository - latest_repo_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") - - # Find directories with changes since the latest tag - mapfile -t changed_dirs < <(git diff --name-only "$latest_repo_tag" -- ':!**/README.md' ':!**/*.test.ts' | xargs dirname | grep -v '^\.' | sort -u) - - echo "Directories with changes: ${changed_dirs[*]}" -fi - -EXIT_CODE=0 - -# Iterate over directories and process versions -for dir in "${changed_dirs[@]}"; do - if [[ -f "$dir/README.md" ]]; then - # Get the module name from the directory - module_name=$(basename "$dir") - - # Get version from README.md - readme_version=$(extract_readme_version "$dir/README.md") - - # Check for module-specific tag with format: release/module-name/v1.0.0 - latest_module_tag=$(git tag -l "release/$module_name/v*" | sort -V | tail -n 1) - if [[ -n "$latest_module_tag" ]]; then - latest_tag_version=$(echo "$latest_module_tag" | sed 's|release/'"$module_name"'/v||') - echo "Module $module_name: Latest tag=$latest_tag_version, README version=$readme_version" - else - echo "Module $module_name: No module-specific tags found, README version=$readme_version" - fi - - # Update version if requested and not in dry-run mode - if [[ "$DRY_RUN" == "false" && "$VERSION_ACTION" == "bump" ]]; then - # Start with the latest tag version if available, otherwise use README version - base_version="" - if [[ -n "$latest_module_tag" ]]; then - base_version="$latest_tag_version" - else - base_version="$readme_version" - fi - target_version=$(get_version "$base_version" "$VERSION_TYPE") - - # Update README if needed - if [[ "$readme_version" == "$target_version" ]]; then - echo "Version in $dir/README.md is already set to $target_version" - else - echo "Updating version in $dir/README.md from $readme_version to $target_version" - update_version_in_readme "$dir/README.md" "$target_version" - - # Create annotated tag if requested - if [[ "$CREATE_TAG" == "true" ]]; then - tag_name="release/$module_name/v$target_version" - echo "Creating annotated tag: $tag_name" - git tag -a "$tag_name" -m "Release $module_name v$target_version" - echo "Remember to push the tag with: git push origin $tag_name" - echo "A GitHub Action will automatically create a PR to update README files when the tag is pushed." - else - echo "To tag this release, use: git tag -a release/$module_name/v$target_version -m \"Release $module_name v$target_version\"" - fi - fi - continue - elif [[ "$DRY_RUN" == "true" && "$VERSION_ACTION" == "bump" ]]; then - # Show what would happen in dry-run mode - base_version="" - if [[ -n "$latest_module_tag" ]]; then - base_version="$latest_tag_version" - else - base_version="$readme_version" - fi - target_version=$(get_version "$base_version" "$VERSION_TYPE") - - echo "[DRY RUN] Would update version in $dir/README.md from $readme_version to $target_version" - if [[ "$CREATE_TAG" == "true" ]]; then - echo "[DRY RUN] Would create annotated tag: release/$module_name/v$target_version" - echo "[DRY RUN] A GitHub Action would create a PR when the tag is pushed" - fi - continue - fi - - # Only do version checking if we're not updating - if [[ "$VERSION_ACTION" != "bump" ]]; then - # Get all tags for the module - module_tags=$(git tag -l "release/$module_name/v*" | sort -V) - - # Skip modules that don't have module-specific tags - if [[ -z "$module_tags" ]]; then - echo "Skipping version check for $dir: No module-specific tags found" - continue - fi - - # Check if README version matches any of the module's tags - version_found=false - for tag in $module_tags; do - tag_version=$(echo "$tag" | sed 's|release/'"$module_name"'/v||') - if [[ "$readme_version" == "$tag_version" ]]; then - version_found=true - echo "✅ Version in $dir/README.md ($readme_version) matches tag $tag" - break - fi - done - - if [[ "$version_found" == "false" ]]; then - echo "❌ ERROR: Version in $dir/README.md ($readme_version) does not match any existing tag" - echo "Available tags:" - echo "$module_tags" - EXIT_CODE=1 - fi - fi - fi -done - -if [[ $EXIT_CODE -eq 0 ]]; then - echo "✅ All checked modules have valid versions" -else - echo "❌ Some modules have version mismatches - see errors above" -fi - -exit $EXIT_CODE diff --git a/release.sh b/release.sh index 509aedad..b4e1c3e7 100755 --- a/release.sh +++ b/release.sh @@ -15,7 +15,7 @@ set -euo pipefail # Default values MODULE_NAME="" VERSION="" -CREATE_TAG=true +DRY_RUN=false LIST_MODULES=false SHOW_HELP=false @@ -52,6 +52,8 @@ for arg in "$@"; do SHOW_HELP=true elif [[ "$arg" == "--list" ]]; then LIST_MODULES=true + elif [[ "$arg" == "--dry-run" ]]; then + DRY_RUN=true elif [[ "$arg" == --version=* ]]; then VERSION="${arg#*=}" # Validate version format @@ -59,8 +61,6 @@ for arg in "$@"; do echo "Error: Version must be in format X.Y.Z (e.g., 1.2.3)" exit 1 fi - elif [[ "$arg" == "--dry-run" ]]; then - CREATE_TAG=false elif [[ "$arg" != --* ]]; then MODULE_NAME="$arg" fi @@ -72,7 +72,7 @@ if [[ "$SHOW_HELP" == "true" ]]; then fi # Function to extract version from README.md -extract_readme_version() { +extract_version() { local file="$1" grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$file" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" } @@ -90,7 +90,7 @@ list_modules() { module_name="${dir%/}" # Get version from README - readme_version=$(extract_readme_version "${dir}README.md") + readme_version=$(extract_version "${dir}README.md") # Get latest tag for this module latest_tag=$(git tag -l "release/${module_name}/v*" | sort -V | tail -n 1) @@ -143,7 +143,7 @@ fi # Get current version from README README_PATH="$MODULE_NAME/README.md" -README_VERSION=$(extract_readme_version "$README_PATH") +README_VERSION=$(extract_version "$README_PATH") # Construct tag name TAG_NAME="release/$MODULE_NAME/v$VERSION" @@ -161,7 +161,7 @@ echo "New tag version: $VERSION" echo "Tag name: $TAG_NAME" # Create the tag -if [[ "$CREATE_TAG" == "true" ]]; then +if [[ "$DRY_RUN" == "false" ]]; then echo "Creating annotated tag..." git tag -a "$TAG_NAME" -m "Release $MODULE_NAME v$VERSION" echo -e "\nSuccess! Tag '$TAG_NAME' created." diff --git a/update-version.sh b/update-version.sh index 8e84be6d..8c318cfd 100755 --- a/update-version.sh +++ b/update-version.sh @@ -8,7 +8,7 @@ # Usage: # ./update-version.sh module-name --version=X.Y.Z # Update README version # ./update-version.sh --help # Show help message -# ./update-version.sh --check module-name # Check if README version matches tag +# ./update-version.sh --check module-name --version=X.Y.Z # Check version set -euo pipefail @@ -34,10 +34,6 @@ Options: Examples: ./update-version.sh code-server --version=1.2.3 # Update version in code-server README ./update-version.sh --check code-server --version=1.2.3 # Check if versions match - -Notes: - - This script is primarily used by GitHub Actions - - It updates the version in README.md files to match module tags EOF exit 0 } @@ -65,14 +61,33 @@ if [[ "$SHOW_HELP" == "true" ]]; then show_help fi +# Validate required parameters +if [[ -z "$MODULE_NAME" ]]; then + echo "Error: Module name is required" + echo "Usage: ./update-version.sh module-name --version=X.Y.Z" + exit 1 +fi + +if [[ -z "$VERSION" ]]; then + echo "Error: Version is required (--version=X.Y.Z)" + echo "Usage: ./update-version.sh module-name --version=X.Y.Z" + exit 1 +fi + +# Verify module directory exists +if [[ ! -d "$MODULE_NAME" || ! -f "$MODULE_NAME/README.md" ]]; then + echo "Error: Module directory '$MODULE_NAME' not found or missing README.md" + exit 1 +fi + # Function to extract version from README.md -extract_readme_version() { +extract_version() { local file="$1" grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$file" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" } # Function to update version in README.md -update_version_in_readme() { +update_version() { local file="$1" local new_version="$2" local tmpfile @@ -81,28 +96,22 @@ update_version_in_readme() { awk -v tag="$new_version" ' BEGIN { in_code_block = 0; in_nested_block = 0 } { - # Detect the start and end of Markdown code blocks. + # Detect code blocks if ($0 ~ /^```/) { in_code_block = !in_code_block - # Reset nested block tracking when exiting a code block. - if (!in_code_block) { - in_nested_block = 0 - } + if (!in_code_block) { in_nested_block = 0 } } - # Handle nested blocks within a code block. + # Track nested blocks within code blocks if (in_code_block) { - # Detect the start of a nested block (skipping "module" blocks). if ($0 ~ /{/ && !($1 == "module" || $1 ~ /^[a-zA-Z0-9_]+$/)) { in_nested_block++ } - - # Detect the end of a nested block. if ($0 ~ /}/ && in_nested_block > 0) { in_nested_block-- } - # Update "version" only if not in a nested block. + # Update version only if not in nested block if (!in_nested_block && $1 == "version" && $2 == "=") { sub(/"[^"]*"/, "\"" tag "\"") } @@ -113,30 +122,9 @@ update_version_in_readme() { ' "$file" > "$tmpfile" && mv "$tmpfile" "$file" } -# Validate required parameters -if [[ -z "$MODULE_NAME" ]]; then - echo "Error: Module name is required" - echo "Usage: ./update-version.sh module-name --version=X.Y.Z" - echo "Run ./update-version.sh --help for more information" - exit 1 -fi - -if [[ -z "$VERSION" ]]; then - echo "Error: Version is required (--version=X.Y.Z)" - echo "Usage: ./update-version.sh module-name --version=X.Y.Z" - echo "Run ./update-version.sh --help for more information" - exit 1 -fi - -# Verify module directory exists -if [[ ! -d "$MODULE_NAME" || ! -f "$MODULE_NAME/README.md" ]]; then - echo "Error: Module directory '$MODULE_NAME' not found or missing README.md" - exit 1 -fi - # Get current version from README README_PATH="$MODULE_NAME/README.md" -README_VERSION=$(extract_readme_version "$README_PATH") +README_VERSION=$(extract_version "$README_PATH") # Report current status echo "Module: $MODULE_NAME" @@ -159,7 +147,7 @@ if [[ "$README_VERSION" == "$VERSION" ]]; then echo "Version in $README_PATH is already set to $VERSION" else echo "Updating version in $README_PATH from $README_VERSION to $VERSION" - update_version_in_readme "$README_PATH" "$VERSION" + update_version "$README_PATH" "$VERSION" echo "✅ Successfully updated version to $VERSION" fi From a6984fb6b5c8e7b0a3aeb8ee84a8badec7c75ecf Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Mon, 14 Apr 2025 20:18:53 +0000 Subject: [PATCH 21/31] refactor: further simplify scripts to bare essentials - Simplify update-version.sh to use positional arguments only - Simplify release.sh to have minimal options - Update GitHub workflow to match new script interfaces - Keep only essential features like --list and --dry-run - Update CONTRIBUTING.md to reflect simplified commands --- .github/workflows/update-readme-version.yaml | 10 +- CONTRIBUTING.md | 2 +- package.json | 3 +- release.sh | 157 +++++-------------- update-version.sh | 71 ++------- 5 files changed, 65 insertions(+), 178 deletions(-) diff --git a/.github/workflows/update-readme-version.yaml b/.github/workflows/update-readme-version.yaml index 4f2cfe8a..3d9d0055 100644 --- a/.github/workflows/update-readme-version.yaml +++ b/.github/workflows/update-readme-version.yaml @@ -47,7 +47,7 @@ jobs: VERSION="${{ steps.tag.outputs.VERSION }}" echo "Checking if README version matches tag version..." - if ./update-version.sh --check "$MODULE" --version="$VERSION"; then + if ./update-version.sh --check "$MODULE" "$VERSION"; then echo "README version already matches tag version" echo "NEEDS_UPDATE=false" >> $GITHUB_OUTPUT else @@ -58,21 +58,17 @@ jobs: - name: Update README version if: steps.check.outputs.NEEDS_UPDATE == 'true' run: | - # Use the existing script to update the README version - # We're forcing an exact version (from the tag) instead of bumping - # Set git identity for the commit git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - # Use update-version.sh to update the README with the exact version from the tag - # This script is specifically designed for this purpose + # Use update-version.sh to update the README version VERSION="${{ steps.tag.outputs.VERSION }}" MODULE="${{ steps.tag.outputs.MODULE_NAME }}" # Update the version in README.md chmod +x ./update-version.sh - ./update-version.sh "$MODULE" --version="$VERSION" + ./update-version.sh "$MODULE" "$VERSION" echo "Updated README version to $VERSION" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eee782c7..f0d4e7fb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -68,7 +68,7 @@ The release process is automated and follows these steps: - Create and push an annotated tag with an appropriate version based on your changes: ```shell # Create an annotated tag with an exact version number - ./release.sh module-name --version=1.2.3 + ./release.sh module-name 1.2.3 # Push the tag to the repository git push origin release/module-name/v1.2.3 diff --git a/package.json b/package.json index 1b18d50d..519d7098 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,7 @@ "fmt": "bun x prettier -w **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt **/*.tf .sample/main.tf", "fmt:ci": "bun x prettier --check **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt -check **/*.tf .sample/main.tf", "lint": "bun run lint.ts && ./terraform_validate.sh", - "release": "./release.sh", - "version:check": "./update-version.sh --check" + "release": "./release.sh" }, "devDependencies": { "bun-types": "^1.1.23", diff --git a/release.sh b/release.sh index b4e1c3e7..f5f44962 100755 --- a/release.sh +++ b/release.sh @@ -1,84 +1,26 @@ #!/usr/bin/env bash # -# release.sh - Create and manage module releases +# release.sh - Create module release tags # -# This script is intended for maintainers to create and manage releases -# by creating annotated tags with appropriate version numbers. +# This script creates annotated tags for module releases which trigger +# the GitHub Actions workflow to update README versions. # # Usage: -# ./release.sh module-name --version=X.Y.Z # Create a tag with specific version -# ./release.sh --help # Show this help message -# ./release.sh --list # List modules with their latest versions +# ./release.sh module-name X.Y.Z # Create a tag with specific version +# ./release.sh --list # List modules with their latest versions +# ./release.sh --dry-run module-name X.Y.Z # Simulate tag creation set -euo pipefail -# Default values -MODULE_NAME="" -VERSION="" -DRY_RUN=false -LIST_MODULES=false -SHOW_HELP=false - -# Function to show usage -show_help() { - cat << EOF -release.sh - Create and manage module releases - -Usage: - ./release.sh [options] module-name - -Options: - --version=X.Y.Z Version number for the new release (required) - --dry-run Show what would happen without making changes - --list List all modules with their latest versions - --help Show this help message - -Examples: - ./release.sh code-server --version=1.2.3 # Create release/code-server/v1.2.3 tag - ./release.sh --list # List all modules and their versions - -Notes: - - This script creates annotated tags that trigger automated README updates - - Tags follow the format: release/module-name/vX.Y.Z - - After creating a tag, you need to push it manually with: - git push origin release/module-name/vX.Y.Z -EOF - exit 0 -} - -# Parse arguments -for arg in "$@"; do - if [[ "$arg" == "--help" ]]; then - SHOW_HELP=true - elif [[ "$arg" == "--list" ]]; then - LIST_MODULES=true - elif [[ "$arg" == "--dry-run" ]]; then - DRY_RUN=true - elif [[ "$arg" == --version=* ]]; then - VERSION="${arg#*=}" - # Validate version format - if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "Error: Version must be in format X.Y.Z (e.g., 1.2.3)" - exit 1 - fi - elif [[ "$arg" != --* ]]; then - MODULE_NAME="$arg" - fi -done - -# Show help if requested -if [[ "$SHOW_HELP" == "true" ]]; then - show_help -fi - -# Function to extract version from README.md -extract_version() { - local file="$1" - grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$file" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" -} +# Check if --list is requested +if [[ "$#" -eq 1 && "$1" == "--list" ]]; then + # Function to extract version from README.md + extract_version() { + local file="$1" + grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$file" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" + } -# Function to list all modules and their latest versions -list_modules() { + # List all modules and their versions echo "Listing all modules and their latest versions:" echo "--------------------------------------------------" printf "%-30s %-15s %s\n" "MODULE" "README VERSION" "LATEST TAG" @@ -86,64 +28,58 @@ list_modules() { for dir in */; do if [[ -d "$dir" && -f "${dir}README.md" && "$dir" != ".git/" ]]; then - # Remove trailing slash module_name="${dir%/}" - - # Get version from README readme_version=$(extract_version "${dir}README.md") - - # Get latest tag for this module latest_tag=$(git tag -l "release/${module_name}/v*" | sort -V | tail -n 1) - if [[ -n "$latest_tag" ]]; then - tag_version=$(echo "$latest_tag" | sed 's|release/'"${module_name}"'/v||') - else - tag_version="none" - fi - + tag_version=$([ -n "$latest_tag" ] && echo "$latest_tag" | sed 's|release/'"${module_name}"'/v||' || echo "none") printf "%-30s %-15s %s\n" "$module_name" "$readme_version" "$tag_version" fi done echo "--------------------------------------------------" - echo "To create a new release: ./release.sh module-name --version=X.Y.Z" + echo "To create a new release: ./release.sh module-name X.Y.Z" exit 0 -} +fi -# Show list of modules if requested -if [[ "$LIST_MODULES" == "true" ]]; then - list_modules +# Check for dry run +DRY_RUN=false +if [[ "$1" == "--dry-run" ]]; then + DRY_RUN=true + shift fi -# Validate required parameters -if [[ -z "$MODULE_NAME" ]]; then - echo "Error: Module name is required" - echo "Usage: ./release.sh module-name --version=X.Y.Z" - echo "Run ./release.sh --help for more information" +# Validate arguments +if [[ "$#" -ne 2 ]]; then + echo "Error: Expected module name and version" + echo "Usage: ./release.sh [--dry-run] module-name X.Y.Z" + echo " or: ./release.sh --list" exit 1 fi -if [[ -z "$VERSION" ]]; then - echo "Error: Version is required (--version=X.Y.Z)" - echo "Usage: ./release.sh module-name --version=X.Y.Z" - echo "Run ./release.sh --help for more information" +# Extract arguments +MODULE_NAME="$1" +VERSION="$2" + +# Validate version format +if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Error: Version must be in format X.Y.Z (e.g., 1.2.3)" exit 1 fi +# Function to extract version from README.md +extract_version() { + local file="$1" + grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$file" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" +} + # Verify module directory exists if [[ ! -d "$MODULE_NAME" || ! -f "$MODULE_NAME/README.md" ]]; then echo "Error: Module directory '$MODULE_NAME' not found or missing README.md" - echo "Available modules:" - for dir in */; do - if [[ -d "$dir" && -f "${dir}README.md" && "$dir" != ".git/" ]]; then - echo " ${dir%/}" - fi - done exit 1 fi # Get current version from README -README_PATH="$MODULE_NAME/README.md" -README_VERSION=$(extract_version "$README_PATH") +README_VERSION=$(extract_version "$MODULE_NAME/README.md") # Construct tag name TAG_NAME="release/$MODULE_NAME/v$VERSION" @@ -162,18 +98,11 @@ echo "Tag name: $TAG_NAME" # Create the tag if [[ "$DRY_RUN" == "false" ]]; then - echo "Creating annotated tag..." git tag -a "$TAG_NAME" -m "Release $MODULE_NAME v$VERSION" - echo -e "\nSuccess! Tag '$TAG_NAME' created." - echo -e "\nTo complete the release:" - echo "1. Push the tag to the repository:" - echo " git push origin $TAG_NAME" - echo "" - echo "2. The GitHub Action will automatically create a PR to update" - echo " the README.md version to match the tag." + echo "Success! Tag '$TAG_NAME' created." + echo "To complete the release: git push origin $TAG_NAME" else echo "[DRY RUN] Would create tag: $TAG_NAME" - echo "[DRY RUN] Tag message: Release $MODULE_NAME v$VERSION" fi exit 0 \ No newline at end of file diff --git a/update-version.sh b/update-version.sh index 8c318cfd..51cae0dd 100755 --- a/update-version.sh +++ b/update-version.sh @@ -6,71 +6,34 @@ # to update README versions after a new tag is pushed. # # Usage: -# ./update-version.sh module-name --version=X.Y.Z # Update README version -# ./update-version.sh --help # Show help message -# ./update-version.sh --check module-name --version=X.Y.Z # Check version +# ./update-version.sh module-name X.Y.Z # Update README version +# ./update-version.sh --check module-name X.Y.Z # Check if versions match set -euo pipefail # Default values -MODULE_NAME="" -VERSION="" CHECK_ONLY=false -SHOW_HELP=false - -# Function to show usage -show_help() { - cat << EOF -update-version.sh - Update README.md version to match module tag - -Usage: - ./update-version.sh [options] module-name - -Options: - --version=X.Y.Z Version number to set in README.md - --check Only check if README version matches specified version - --help Show this help message - -Examples: - ./update-version.sh code-server --version=1.2.3 # Update version in code-server README - ./update-version.sh --check code-server --version=1.2.3 # Check if versions match -EOF - exit 0 -} - -# Parse arguments -for arg in "$@"; do - if [[ "$arg" == "--help" ]]; then - SHOW_HELP=true - elif [[ "$arg" == "--check" ]]; then - CHECK_ONLY=true - elif [[ "$arg" == --version=* ]]; then - VERSION="${arg#*=}" - # Validate version format - if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "Error: Version must be in format X.Y.Z (e.g., 1.2.3)" - exit 1 - fi - elif [[ "$arg" != --* ]]; then - MODULE_NAME="$arg" - fi -done -# Show help if requested -if [[ "$SHOW_HELP" == "true" ]]; then - show_help +# Parse --check flag if present +if [[ "$1" == "--check" ]]; then + CHECK_ONLY=true + shift fi -# Validate required parameters -if [[ -z "$MODULE_NAME" ]]; then - echo "Error: Module name is required" - echo "Usage: ./update-version.sh module-name --version=X.Y.Z" +# Validate we have exactly two parameters: module name and version +if [[ "$#" -ne 2 ]]; then + echo "Error: Expected module name and version" + echo "Usage: ./update-version.sh [--check] module-name X.Y.Z" exit 1 fi -if [[ -z "$VERSION" ]]; then - echo "Error: Version is required (--version=X.Y.Z)" - echo "Usage: ./update-version.sh module-name --version=X.Y.Z" +# Extract arguments +MODULE_NAME="$1" +VERSION="$2" + +# Validate version format +if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Error: Version must be in format X.Y.Z (e.g., 1.2.3)" exit 1 fi From 0c4f9548ec5ecd1b4a3de72be6fd9dad5528702a Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Mon, 14 Apr 2025 20:25:32 +0000 Subject: [PATCH 22/31] feat: use GitHub CLI for PR management - Replace peter-evans/create-pull-request with gh CLI - Set github-actions[bot] as PR author - Request review from cdr-bot for approval - Enable auto-merge using the gh pr merge command - Extract PR number for proper API integration --- .github/workflows/update-readme-version.yaml | 71 ++++++++++++-------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/.github/workflows/update-readme-version.yaml b/.github/workflows/update-readme-version.yaml index 3d9d0055..42e92473 100644 --- a/.github/workflows/update-readme-version.yaml +++ b/.github/workflows/update-readme-version.yaml @@ -72,35 +72,50 @@ jobs: echo "Updated README version to $VERSION" - - name: Create Pull Request + - name: Create and Auto-Merge PR if: steps.check.outputs.NEEDS_UPDATE == 'true' - id: create-pr - uses: peter-evans/create-pull-request@v6 - with: - commit-message: "chore: update ${{ steps.tag.outputs.MODULE_NAME }} version to ${{ steps.tag.outputs.VERSION }}" - branch: automated-readme-update-${{ steps.tag.outputs.MODULE_NAME }}-${{ steps.tag.outputs.VERSION }} - base: main - title: "chore: update ${{ steps.tag.outputs.MODULE_NAME }} version to ${{ steps.tag.outputs.VERSION }}" - body: | - This PR automatically updates the README version to match the newly created tag. + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # Variables for PR creation + MODULE="${{ steps.tag.outputs.MODULE_NAME }}" + VERSION="${{ steps.tag.outputs.VERSION }}" + TAG="${{ steps.tag.outputs.TAG_NAME }}" + BRANCH="automated-readme-update-$MODULE-$VERSION" + PR_TITLE="chore: update $MODULE version to $VERSION" + + # Create a branch for the PR + git checkout -b "$BRANCH" + + # Commit the changes + git add "$MODULE/README.md" + git commit -m "$PR_TITLE" --author="github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>" + + # Push the branch + git push origin "$BRANCH" + + # Create PR using GitHub CLI + PR_URL=$(gh pr create \ + --title "$PR_TITLE" \ + --body "This PR automatically updates the README version to match the newly created tag. - Tag: ${{ steps.tag.outputs.TAG_NAME }} - Module: ${{ steps.tag.outputs.MODULE_NAME }} - Version: ${{ steps.tag.outputs.VERSION }} + Tag: $TAG + Module: $MODULE + Version: $VERSION - This PR has been automatically approved and enabled for auto-merge. - delete-branch: true - - - name: Auto-approve PR - if: steps.create-pr.outputs.pull-request-number - uses: hmarr/auto-approve-action@v3 - with: - pull-request-number: ${{ steps.create-pr.outputs.pull-request-number }} + This PR will be automatically approved and merged." \ + --base main \ + --head "$BRANCH") - - name: Enable auto-merge - if: steps.create-pr.outputs.pull-request-number - run: | - # Enable auto-merge using GitHub CLI - gh pr merge ${{ steps.create-pr.outputs.pull-request-number }} --auto --squash - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + echo "Created PR: $PR_URL" + + # Extract PR number from URL + PR_NUMBER=$(echo "$PR_URL" | grep -o '[0-9]*$') + + # Request review from cdr-bot + gh pr review "$PR_NUMBER" --request --reviewer "cdr-bot" + + # Enable auto-merge + gh pr merge "$PR_NUMBER" --auto --squash + + echo "PR has been created, requested cdr-bot review, and set to auto-merge" \ No newline at end of file From fb3ae6f450bdafc75f83c068f0c8f528e3bb480b Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Mon, 14 Apr 2025 20:29:14 +0000 Subject: [PATCH 23/31] refactor: use cdrci as PR author and auto-approve action - Change PR author to cdrci - Implement auto-approve using hmarr/auto-approve-action - Follow GitHub's recommended pattern for auto-approval - Separate PR creation and approval into distinct steps - Pass PR number between steps using GITHUB_OUTPUT --- .github/workflows/update-readme-version.yaml | 22 ++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/.github/workflows/update-readme-version.yaml b/.github/workflows/update-readme-version.yaml index 42e92473..6cb8d623 100644 --- a/.github/workflows/update-readme-version.yaml +++ b/.github/workflows/update-readme-version.yaml @@ -72,10 +72,11 @@ jobs: echo "Updated README version to $VERSION" - - name: Create and Auto-Merge PR + - name: Create PR if: steps.check.outputs.NEEDS_UPDATE == 'true' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + id: create-pr run: | # Variables for PR creation MODULE="${{ steps.tag.outputs.MODULE_NAME }}" @@ -87,9 +88,13 @@ jobs: # Create a branch for the PR git checkout -b "$BRANCH" + # Configure git for cdrci user + git config user.name "cdrci" + git config user.email "cdrci@users.noreply.github.com" + # Commit the changes git add "$MODULE/README.md" - git commit -m "$PR_TITLE" --author="github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>" + git commit -m "$PR_TITLE" # Push the branch git push origin "$BRANCH" @@ -111,11 +116,16 @@ jobs: # Extract PR number from URL PR_NUMBER=$(echo "$PR_URL" | grep -o '[0-9]*$') - - # Request review from cdr-bot - gh pr review "$PR_NUMBER" --request --reviewer "cdr-bot" + echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT # Enable auto-merge gh pr merge "$PR_NUMBER" --auto --squash - echo "PR has been created, requested cdr-bot review, and set to auto-merge" \ No newline at end of file + echo "PR has been created and set to auto-merge" + + - name: Auto-approve PR + if: steps.create-pr.outputs.pr_number + uses: hmarr/auto-approve-action@v3 + with: + pull-request-number: ${{ steps.create-pr.outputs.pr_number }} + github-token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 6d925cafe19de810a4424d44daa0a5588060c6e4 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Mon, 14 Apr 2025 20:32:16 +0000 Subject: [PATCH 24/31] refactor: remove unnecessary comments and streamline code - Remove all superfluous comments from scripts - Simplify scripts to be more concise - Streamline GitHub Actions workflow syntax - Keep only essential code and explanations --- .github/workflows/update-readme-version.yaml | 85 +++++--------------- release.sh | 38 ++------- update-version.sh | 59 ++------------ 3 files changed, 31 insertions(+), 151 deletions(-) diff --git a/.github/workflows/update-readme-version.yaml b/.github/workflows/update-readme-version.yaml index 6cb8d623..127c6cd1 100644 --- a/.github/workflows/update-readme-version.yaml +++ b/.github/workflows/update-readme-version.yaml @@ -3,7 +3,7 @@ name: Auto Update README Version on: push: tags: - - 'release/*/v*' # Matches tags like release/module-name/v1.0.0 + - 'release/*/v*' jobs: update-readme: @@ -13,23 +13,18 @@ jobs: pull-requests: write steps: - - name: Checkout repository - uses: actions/checkout@v4 + - uses: actions/checkout@v4 with: - fetch-depth: 0 # Need full history for tags + fetch-depth: 0 - - name: Set up Bun - uses: oven-sh/setup-bun@v2 + - uses: oven-sh/setup-bun@v2 with: bun-version: latest - - name: Install dependencies - run: bun install + - run: bun install - - name: Extract tag information - id: tag + - id: tag run: | - # Extract module name and version from tag TAG_NAME="${GITHUB_REF#refs/tags/}" MODULE_NAME=$(echo $TAG_NAME | cut -d'/' -f2) VERSION=$(echo $TAG_NAME | cut -d'/' -f3 | sed 's/^v//') @@ -38,93 +33,49 @@ jobs: echo "VERSION=$VERSION" >> $GITHUB_OUTPUT echo "TAG_NAME=$TAG_NAME" >> $GITHUB_OUTPUT - - name: Check if README needs updating - id: check + - id: check run: | - # Use the update-version.sh script in check mode chmod +x ./update-version.sh - MODULE="${{ steps.tag.outputs.MODULE_NAME }}" - VERSION="${{ steps.tag.outputs.VERSION }}" - - echo "Checking if README version matches tag version..." - if ./update-version.sh --check "$MODULE" "$VERSION"; then - echo "README version already matches tag version" + if ./update-version.sh --check "${{ steps.tag.outputs.MODULE_NAME }}" "${{ steps.tag.outputs.VERSION }}"; then echo "NEEDS_UPDATE=false" >> $GITHUB_OUTPUT else - echo "README version does not match tag version - update needed" echo "NEEDS_UPDATE=true" >> $GITHUB_OUTPUT fi - - name: Update README version - if: steps.check.outputs.NEEDS_UPDATE == 'true' + - if: steps.check.outputs.NEEDS_UPDATE == 'true' run: | - # Set git identity for the commit - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - - # Use update-version.sh to update the README version - VERSION="${{ steps.tag.outputs.VERSION }}" - MODULE="${{ steps.tag.outputs.MODULE_NAME }}" - - # Update the version in README.md + git config user.name "cdrci" + git config user.email "cdrci@users.noreply.github.com" chmod +x ./update-version.sh - ./update-version.sh "$MODULE" "$VERSION" - - echo "Updated README version to $VERSION" + ./update-version.sh "${{ steps.tag.outputs.MODULE_NAME }}" "${{ steps.tag.outputs.VERSION }}" - - name: Create PR - if: steps.check.outputs.NEEDS_UPDATE == 'true' + - if: steps.check.outputs.NEEDS_UPDATE == 'true' + id: create-pr env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - id: create-pr run: | - # Variables for PR creation MODULE="${{ steps.tag.outputs.MODULE_NAME }}" VERSION="${{ steps.tag.outputs.VERSION }}" - TAG="${{ steps.tag.outputs.TAG_NAME }}" - BRANCH="automated-readme-update-$MODULE-$VERSION" + BRANCH="automated-update-$MODULE-$VERSION" PR_TITLE="chore: update $MODULE version to $VERSION" - # Create a branch for the PR git checkout -b "$BRANCH" - - # Configure git for cdrci user - git config user.name "cdrci" - git config user.email "cdrci@users.noreply.github.com" - - # Commit the changes git add "$MODULE/README.md" git commit -m "$PR_TITLE" - - # Push the branch git push origin "$BRANCH" - # Create PR using GitHub CLI PR_URL=$(gh pr create \ --title "$PR_TITLE" \ - --body "This PR automatically updates the README version to match the newly created tag. - - Tag: $TAG - Module: $MODULE - Version: $VERSION - - This PR will be automatically approved and merged." \ + --body "Updates README version to match tag ${{ steps.tag.outputs.TAG_NAME }}" \ --base main \ --head "$BRANCH") - echo "Created PR: $PR_URL" - - # Extract PR number from URL PR_NUMBER=$(echo "$PR_URL" | grep -o '[0-9]*$') echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT - # Enable auto-merge gh pr merge "$PR_NUMBER" --auto --squash - - echo "PR has been created and set to auto-merge" - - - name: Auto-approve PR - if: steps.create-pr.outputs.pr_number + + - if: steps.create-pr.outputs.pr_number uses: hmarr/auto-approve-action@v3 with: pull-request-number: ${{ steps.create-pr.outputs.pr_number }} diff --git a/release.sh b/release.sh index f5f44962..70627691 100755 --- a/release.sh +++ b/release.sh @@ -1,26 +1,13 @@ #!/usr/bin/env bash -# -# release.sh - Create module release tags -# -# This script creates annotated tags for module releases which trigger -# the GitHub Actions workflow to update README versions. -# -# Usage: -# ./release.sh module-name X.Y.Z # Create a tag with specific version -# ./release.sh --list # List modules with their latest versions -# ./release.sh --dry-run module-name X.Y.Z # Simulate tag creation +# release.sh - Creates annotated tags for module releases set -euo pipefail -# Check if --list is requested if [[ "$#" -eq 1 && "$1" == "--list" ]]; then - # Function to extract version from README.md extract_version() { - local file="$1" - grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$file" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" + grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$1" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" } - # List all modules and their versions echo "Listing all modules and their latest versions:" echo "--------------------------------------------------" printf "%-30s %-15s %s\n" "MODULE" "README VERSION" "LATEST TAG" @@ -37,66 +24,51 @@ if [[ "$#" -eq 1 && "$1" == "--list" ]]; then done echo "--------------------------------------------------" - echo "To create a new release: ./release.sh module-name X.Y.Z" exit 0 fi -# Check for dry run DRY_RUN=false if [[ "$1" == "--dry-run" ]]; then DRY_RUN=true shift fi -# Validate arguments if [[ "$#" -ne 2 ]]; then - echo "Error: Expected module name and version" echo "Usage: ./release.sh [--dry-run] module-name X.Y.Z" echo " or: ./release.sh --list" exit 1 fi -# Extract arguments MODULE_NAME="$1" VERSION="$2" -# Validate version format if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "Error: Version must be in format X.Y.Z (e.g., 1.2.3)" + echo "Error: Version must be in format X.Y.Z" exit 1 fi -# Function to extract version from README.md extract_version() { - local file="$1" - grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$file" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" + grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$1" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" } -# Verify module directory exists if [[ ! -d "$MODULE_NAME" || ! -f "$MODULE_NAME/README.md" ]]; then - echo "Error: Module directory '$MODULE_NAME' not found or missing README.md" + echo "Error: Module directory not found or missing README.md" exit 1 fi -# Get current version from README README_VERSION=$(extract_version "$MODULE_NAME/README.md") - -# Construct tag name TAG_NAME="release/$MODULE_NAME/v$VERSION" -# Check if tag already exists if git rev-parse -q --verify "refs/tags/$TAG_NAME" >/dev/null; then echo "Error: Tag $TAG_NAME already exists" exit 1 fi -# Report what will happen echo "Module: $MODULE_NAME" echo "Current README version: $README_VERSION" echo "New tag version: $VERSION" echo "Tag name: $TAG_NAME" -# Create the tag if [[ "$DRY_RUN" == "false" ]]; then git tag -a "$TAG_NAME" -m "Release $MODULE_NAME v$VERSION" echo "Success! Tag '$TAG_NAME' created." diff --git a/update-version.sh b/update-version.sh index 51cae0dd..8a9bd61b 100755 --- a/update-version.sh +++ b/update-version.sh @@ -1,71 +1,45 @@ #!/usr/bin/env bash -# -# update-version.sh - Update README.md version to match module tag -# -# This script is primarily used by the GitHub Actions workflow -# to update README versions after a new tag is pushed. -# -# Usage: -# ./update-version.sh module-name X.Y.Z # Update README version -# ./update-version.sh --check module-name X.Y.Z # Check if versions match +# update-version.sh - Updates or checks README.md version set -euo pipefail -# Default values CHECK_ONLY=false - -# Parse --check flag if present if [[ "$1" == "--check" ]]; then CHECK_ONLY=true shift fi -# Validate we have exactly two parameters: module name and version if [[ "$#" -ne 2 ]]; then - echo "Error: Expected module name and version" echo "Usage: ./update-version.sh [--check] module-name X.Y.Z" exit 1 fi -# Extract arguments MODULE_NAME="$1" VERSION="$2" -# Validate version format if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "Error: Version must be in format X.Y.Z (e.g., 1.2.3)" + echo "Error: Version must be in format X.Y.Z" exit 1 fi -# Verify module directory exists if [[ ! -d "$MODULE_NAME" || ! -f "$MODULE_NAME/README.md" ]]; then - echo "Error: Module directory '$MODULE_NAME' not found or missing README.md" + echo "Error: Module directory not found or missing README.md" exit 1 fi -# Function to extract version from README.md extract_version() { - local file="$1" - grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$file" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" + grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$1" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" } -# Function to update version in README.md update_version() { - local file="$1" - local new_version="$2" - local tmpfile - - tmpfile=$(mktemp /tmp/tempfile.XXXXXX) - awk -v tag="$new_version" ' + local tmpfile=$(mktemp) + awk -v tag="$2" ' BEGIN { in_code_block = 0; in_nested_block = 0 } { - # Detect code blocks if ($0 ~ /^```/) { in_code_block = !in_code_block if (!in_code_block) { in_nested_block = 0 } } - - # Track nested blocks within code blocks if (in_code_block) { if ($0 ~ /{/ && !($1 == "module" || $1 ~ /^[a-zA-Z0-9_]+$/)) { in_nested_block++ @@ -73,45 +47,28 @@ update_version() { if ($0 ~ /}/ && in_nested_block > 0) { in_nested_block-- } - - # Update version only if not in nested block if (!in_nested_block && $1 == "version" && $2 == "=") { sub(/"[^"]*"/, "\"" tag "\"") } } - print } - ' "$file" > "$tmpfile" && mv "$tmpfile" "$file" + ' "$1" > "$tmpfile" && mv "$tmpfile" "$1" } -# Get current version from README README_PATH="$MODULE_NAME/README.md" README_VERSION=$(extract_version "$README_PATH") -# Report current status -echo "Module: $MODULE_NAME" -echo "Current README version: $README_VERSION" -echo "Target version: $VERSION" - -# In check mode, just report if versions match if [[ "$CHECK_ONLY" == "true" ]]; then if [[ "$README_VERSION" == "$VERSION" ]]; then - echo "✅ Version in README.md matches target version: $VERSION" exit 0 else - echo "❌ Version mismatch: README.md has $README_VERSION, target is $VERSION" exit 1 fi fi -# Update README if versions differ -if [[ "$README_VERSION" == "$VERSION" ]]; then - echo "Version in $README_PATH is already set to $VERSION" -else - echo "Updating version in $README_PATH from $README_VERSION to $VERSION" +if [[ "$README_VERSION" != "$VERSION" ]]; then update_version "$README_PATH" "$VERSION" - echo "✅ Successfully updated version to $VERSION" fi exit 0 \ No newline at end of file From bdd8dba75315a20ca4d66dec9dfd2558bc2e4fdf Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Mon, 14 Apr 2025 20:34:37 +0000 Subject: [PATCH 25/31] docs: add helpful comments to scripts and workflow - Add explanatory comments to update-version.sh - Add detailed section comments to release.sh - Add workflow-level comments to GitHub Actions file - Explain purpose of each major code section - Enhance readability for maintainers and reviewers --- .github/workflows/update-readme-version.yaml | 70 ++++++++++++++++---- release.sh | 30 +++++++++ update-version.sh | 25 +++++++ 3 files changed, 113 insertions(+), 12 deletions(-) diff --git a/.github/workflows/update-readme-version.yaml b/.github/workflows/update-readme-version.yaml index 127c6cd1..9d3f7f18 100644 --- a/.github/workflows/update-readme-version.yaml +++ b/.github/workflows/update-readme-version.yaml @@ -1,81 +1,127 @@ name: Auto Update README Version +# This workflow runs when a new tag is pushed with the format release/module-name/vX.Y.Z +# It automatically updates the corresponding README.md file with the new version +# and creates a PR that is auto-approved and auto-merged. + on: push: tags: - - 'release/*/v*' + - 'release/*/v*' # Matches tags like release/module-name/v1.0.0 jobs: update-readme: runs-on: ubuntu-latest permissions: - contents: write - pull-requests: write + contents: write # Needed to push branches + pull-requests: write # Needed to create and manage PRs steps: - - uses: actions/checkout@v4 + # Check out the repository + - name: Checkout code + uses: actions/checkout@v4 with: - fetch-depth: 0 + fetch-depth: 0 # We need the full history to check tags - - uses: oven-sh/setup-bun@v2 + # Set up the Bun JavaScript runtime + - name: Setup Bun + uses: oven-sh/setup-bun@v2 with: bun-version: latest - - run: bun install + # Install dependencies + - name: Install dependencies + run: bun install - - id: tag + # Extract information from the tag that triggered this workflow + - name: Extract tag information + id: tag run: | + # Parse the tag name (e.g., "release/code-server/v1.2.3") TAG_NAME="${GITHUB_REF#refs/tags/}" + # Extract module name (the middle part) MODULE_NAME=$(echo $TAG_NAME | cut -d'/' -f2) + # Extract version (the last part, without the 'v' prefix) VERSION=$(echo $TAG_NAME | cut -d'/' -f3 | sed 's/^v//') + # Make these values available to other steps echo "MODULE_NAME=$MODULE_NAME" >> $GITHUB_OUTPUT echo "VERSION=$VERSION" >> $GITHUB_OUTPUT echo "TAG_NAME=$TAG_NAME" >> $GITHUB_OUTPUT - - id: check + # Check if README needs updating + - name: Check if README version needs updating + id: check run: | + # Make the script executable chmod +x ./update-version.sh + + # Check if README version matches tag version + # The script will exit with 0 if versions match, 1 if they don't if ./update-version.sh --check "${{ steps.tag.outputs.MODULE_NAME }}" "${{ steps.tag.outputs.VERSION }}"; then echo "NEEDS_UPDATE=false" >> $GITHUB_OUTPUT + echo "README version already matches tag version - no update needed" else echo "NEEDS_UPDATE=true" >> $GITHUB_OUTPUT + echo "README version doesn't match tag version - update needed" fi - - if: steps.check.outputs.NEEDS_UPDATE == 'true' + # Update README with new version + - name: Update README version + if: steps.check.outputs.NEEDS_UPDATE == 'true' run: | + # Set git identity for commits git config user.name "cdrci" git config user.email "cdrci@users.noreply.github.com" + + # Update the README with the new version chmod +x ./update-version.sh ./update-version.sh "${{ steps.tag.outputs.MODULE_NAME }}" "${{ steps.tag.outputs.VERSION }}" + echo "Updated README version to ${{ steps.tag.outputs.VERSION }}" - - if: steps.check.outputs.NEEDS_UPDATE == 'true' + # Create PR with the changes + - name: Create PR for version update + if: steps.check.outputs.NEEDS_UPDATE == 'true' id: create-pr env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | + # Set variables for PR creation MODULE="${{ steps.tag.outputs.MODULE_NAME }}" VERSION="${{ steps.tag.outputs.VERSION }}" BRANCH="automated-update-$MODULE-$VERSION" PR_TITLE="chore: update $MODULE version to $VERSION" + # Create a branch for the PR git checkout -b "$BRANCH" + + # Commit the changes git add "$MODULE/README.md" git commit -m "$PR_TITLE" + + # Push the branch to the repository git push origin "$BRANCH" + # Create a PR using GitHub CLI PR_URL=$(gh pr create \ --title "$PR_TITLE" \ --body "Updates README version to match tag ${{ steps.tag.outputs.TAG_NAME }}" \ --base main \ --head "$BRANCH") + echo "Created PR: $PR_URL" + + # Extract PR number from the URL PR_NUMBER=$(echo "$PR_URL" | grep -o '[0-9]*$') echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT + # Enable auto-merge for the PR gh pr merge "$PR_NUMBER" --auto --squash + echo "Enabled auto-merge for PR #$PR_NUMBER" - - if: steps.create-pr.outputs.pr_number + # Auto-approve the PR + - name: Auto-approve PR + if: steps.create-pr.outputs.pr_number uses: hmarr/auto-approve-action@v3 with: pull-request-number: ${{ steps.create-pr.outputs.pr_number }} diff --git a/release.sh b/release.sh index 70627691..62834e32 100755 --- a/release.sh +++ b/release.sh @@ -1,24 +1,39 @@ #!/usr/bin/env bash +# # release.sh - Creates annotated tags for module releases +# +# This script is used by maintainers to create annotated tags for module releases. +# It supports two main modes: +# 1. Creating a new tag for a module: ./release.sh module-name X.Y.Z +# 2. Listing all modules with their versions: ./release.sh --list +# +# When a tag is pushed, it triggers a GitHub workflow that updates README versions. set -euo pipefail +# Handle --list option to show all modules and their versions if [[ "$#" -eq 1 && "$1" == "--list" ]]; then + # Function to extract version from README extract_version() { grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$1" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" } + # Display header for module listing echo "Listing all modules and their latest versions:" echo "--------------------------------------------------" printf "%-30s %-15s %s\n" "MODULE" "README VERSION" "LATEST TAG" echo "--------------------------------------------------" + # Loop through all directories that look like modules for dir in */; do if [[ -d "$dir" && -f "${dir}README.md" && "$dir" != ".git/" ]]; then module_name="${dir%/}" + # Get version from README readme_version=$(extract_version "${dir}README.md") + # Get latest tag for this module latest_tag=$(git tag -l "release/${module_name}/v*" | sort -V | tail -n 1) tag_version=$([ -n "$latest_tag" ] && echo "$latest_tag" | sed 's|release/'"${module_name}"'/v||' || echo "none") + # Display module info printf "%-30s %-15s %s\n" "$module_name" "$readme_version" "$tag_version" fi done @@ -27,12 +42,14 @@ if [[ "$#" -eq 1 && "$1" == "--list" ]]; then exit 0 fi +# Handle --dry-run option DRY_RUN=false if [[ "$1" == "--dry-run" ]]; then DRY_RUN=true shift fi +# Validate arguments if [[ "$#" -ne 2 ]]; then echo "Usage: ./release.sh [--dry-run] module-name X.Y.Z" echo " or: ./release.sh --list" @@ -42,37 +59,50 @@ fi MODULE_NAME="$1" VERSION="$2" +# Validate version format if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "Error: Version must be in format X.Y.Z" exit 1 fi +# Function to extract version from README extract_version() { grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$1" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" } +# Check if module exists if [[ ! -d "$MODULE_NAME" || ! -f "$MODULE_NAME/README.md" ]]; then echo "Error: Module directory not found or missing README.md" exit 1 fi +# Get current README version and construct tag name README_VERSION=$(extract_version "$MODULE_NAME/README.md") TAG_NAME="release/$MODULE_NAME/v$VERSION" +# Check if tag already exists if git rev-parse -q --verify "refs/tags/$TAG_NAME" >/dev/null; then echo "Error: Tag $TAG_NAME already exists" exit 1 fi +# Display release information echo "Module: $MODULE_NAME" echo "Current README version: $README_VERSION" echo "New tag version: $VERSION" echo "Tag name: $TAG_NAME" +# Create the tag (or simulate in dry-run mode) if [[ "$DRY_RUN" == "false" ]]; then + # Create annotated tag git tag -a "$TAG_NAME" -m "Release $MODULE_NAME v$VERSION" echo "Success! Tag '$TAG_NAME' created." echo "To complete the release: git push origin $TAG_NAME" + echo "" + echo "When pushed, this will trigger the GitHub Action to:" + echo "- Update the README.md version" + echo "- Create a PR with the update" + echo "- Auto-approve and merge the PR" else echo "[DRY RUN] Would create tag: $TAG_NAME" fi diff --git a/update-version.sh b/update-version.sh index 8a9bd61b..36ff4c79 100755 --- a/update-version.sh +++ b/update-version.sh @@ -1,14 +1,23 @@ #!/usr/bin/env bash +# # update-version.sh - Updates or checks README.md version +# +# This script is used for two main purposes: +# 1. Update the version in a module's README.md file (normal mode) +# 2. Check if the version in README.md matches a specified version (--check mode) +# +# It's primarily used by the GitHub Actions workflow that runs when tags are pushed. set -euo pipefail +# Check if we're in check-only mode CHECK_ONLY=false if [[ "$1" == "--check" ]]; then CHECK_ONLY=true shift fi +# Validate we have the right number of arguments if [[ "$#" -ne 2 ]]; then echo "Usage: ./update-version.sh [--check] module-name X.Y.Z" exit 1 @@ -17,29 +26,39 @@ fi MODULE_NAME="$1" VERSION="$2" +# Validate version format (X.Y.Z) if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "Error: Version must be in format X.Y.Z" exit 1 fi +# Check if module directory exists if [[ ! -d "$MODULE_NAME" || ! -f "$MODULE_NAME/README.md" ]]; then echo "Error: Module directory not found or missing README.md" exit 1 fi +# Extract version from README.md file extract_version() { + # This finds version lines like: version = "1.2.3" grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$1" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" } +# Update version in README.md file update_version() { local tmpfile=$(mktemp) + # This awk script finds and updates version lines in code blocks + # It's careful to only update version lines in the right context (not in nested blocks) awk -v tag="$2" ' BEGIN { in_code_block = 0; in_nested_block = 0 } { + # Track code blocks (```...```) if ($0 ~ /^```/) { in_code_block = !in_code_block if (!in_code_block) { in_nested_block = 0 } } + + # Inside code blocks, track nested {} blocks if (in_code_block) { if ($0 ~ /{/ && !($1 == "module" || $1 ~ /^[a-zA-Z0-9_]+$/)) { in_nested_block++ @@ -47,6 +66,8 @@ update_version() { if ($0 ~ /}/ && in_nested_block > 0) { in_nested_block-- } + + # Only update version if not in a nested block if (!in_nested_block && $1 == "version" && $2 == "=") { sub(/"[^"]*"/, "\"" tag "\"") } @@ -59,14 +80,18 @@ update_version() { README_PATH="$MODULE_NAME/README.md" README_VERSION=$(extract_version "$README_PATH") +# In check mode, just return success/failure based on version match if [[ "$CHECK_ONLY" == "true" ]]; then if [[ "$README_VERSION" == "$VERSION" ]]; then + # Success: versions match exit 0 else + # Failure: versions don't match exit 1 fi fi +# Update the version if needed if [[ "$README_VERSION" != "$VERSION" ]]; then update_version "$README_PATH" "$VERSION" fi From 3f0615b8ed7534ce95c48c1b64c452752d515540 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Mon, 14 Apr 2025 20:46:31 +0000 Subject: [PATCH 26/31] fmt --- CONTRIBUTING.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f0d4e7fb..c2971a16 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -59,13 +59,16 @@ module "example" { The release process is automated and follows these steps: 1. Create a PR with your module changes + - You **do not** need to update the version number in the README.md file - Focus on implementing your feature or fix 2. Have your PR reviewed, approved, and merged to main 3. After merging to main, a maintainer will: + - Create and push an annotated tag with an appropriate version based on your changes: + ```shell # Create an annotated tag with an exact version number ./release.sh module-name 1.2.3 @@ -73,11 +76,13 @@ The release process is automated and follows these steps: # Push the tag to the repository git push origin release/module-name/v1.2.3 ``` - + - View all modules and their current versions with: + ```shell ./release.sh --list ``` + - The tag will follow the format: `release/module-name/v1.0.0` 4. When the tag is pushed, a GitHub Action will automatically: From 8200f2dfc7c8e8e1baa2217078f80af69a62093a Mon Sep 17 00:00:00 2001 From: M Atif Ali Date: Tue, 15 Apr 2025 01:51:46 +0500 Subject: [PATCH 27/31] Remove release script from package.json --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 519d7098..247f5a3b 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,6 @@ "fmt": "bun x prettier -w **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt **/*.tf .sample/main.tf", "fmt:ci": "bun x prettier --check **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt -check **/*.tf .sample/main.tf", "lint": "bun run lint.ts && ./terraform_validate.sh", - "release": "./release.sh" }, "devDependencies": { "bun-types": "^1.1.23", From 70e5da72c003fa1dc837a7689f1d395bf589baca Mon Sep 17 00:00:00 2001 From: M Atif Ali Date: Tue, 15 Apr 2025 01:53:35 +0500 Subject: [PATCH 28/31] Remove trailing comma in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 247f5a3b..873ac51b 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "test": "bun test", "fmt": "bun x prettier -w **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt **/*.tf .sample/main.tf", "fmt:ci": "bun x prettier --check **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt -check **/*.tf .sample/main.tf", - "lint": "bun run lint.ts && ./terraform_validate.sh", + "lint": "bun run lint.ts && ./terraform_validate.sh" }, "devDependencies": { "bun-types": "^1.1.23", From e4e5c7379ef33b5b149ac3c4be2b42e2562a1efc Mon Sep 17 00:00:00 2001 From: M Atif Ali Date: Tue, 15 Apr 2025 02:03:21 +0500 Subject: [PATCH 29/31] Remove commented-out version check steps in CI --- .github/workflows/ci.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index afb17a37..f032d79a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -51,7 +51,3 @@ jobs: uses: crate-ci/typos@v1.17.2 - name: Lint run: bun lint - - # No need to verify module versions in PRs now - # Version checks will be handled by the maintainer after merging - # And automated PRs will update the README.md files From 57fc91f0a658e9f458932e6da672f8b70c669dec Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Tue, 15 Apr 2025 13:14:33 +0000 Subject: [PATCH 30/31] Simplify and improve GitHub workflow and release scripts --- .github/workflows/update-readme-version.yaml | 104 +++++++------------ release.sh | 99 +++++++++++------- update-version.sh | 72 +++++++++---- 3 files changed, 150 insertions(+), 125 deletions(-) diff --git a/.github/workflows/update-readme-version.yaml b/.github/workflows/update-readme-version.yaml index 9d3f7f18..9929be7d 100644 --- a/.github/workflows/update-readme-version.yaml +++ b/.github/workflows/update-readme-version.yaml @@ -1,39 +1,31 @@ name: Auto Update README Version -# This workflow runs when a new tag is pushed with the format release/module-name/vX.Y.Z -# It automatically updates the corresponding README.md file with the new version -# and creates a PR that is auto-approved and auto-merged. - on: push: tags: - - 'release/*/v*' # Matches tags like release/module-name/v1.0.0 + - "release/*/v*" # Matches tags like release/module-name/v1.0.0 jobs: update-readme: runs-on: ubuntu-latest permissions: - contents: write # Needed to push branches - pull-requests: write # Needed to create and manage PRs - + contents: write + pull-requests: write + steps: - # Check out the repository - name: Checkout code uses: actions/checkout@v4 with: - fetch-depth: 0 # We need the full history to check tags - - # Set up the Bun JavaScript runtime + fetch-depth: 0 + - name: Setup Bun uses: oven-sh/setup-bun@v2 with: bun-version: latest - - # Install dependencies + - name: Install dependencies run: bun install - - # Extract information from the tag that triggered this workflow + - name: Extract tag information id: tag run: | @@ -43,86 +35,64 @@ jobs: MODULE_NAME=$(echo $TAG_NAME | cut -d'/' -f2) # Extract version (the last part, without the 'v' prefix) VERSION=$(echo $TAG_NAME | cut -d'/' -f3 | sed 's/^v//') - + # Make these values available to other steps echo "MODULE_NAME=$MODULE_NAME" >> $GITHUB_OUTPUT echo "VERSION=$VERSION" >> $GITHUB_OUTPUT echo "TAG_NAME=$TAG_NAME" >> $GITHUB_OUTPUT - - # Check if README needs updating + - name: Check if README version needs updating id: check + env: + MODULE_NAME: ${{steps.tag.outputs.MODULE_NAME}} + VERSION: ${{steps.tag.outputs.VERSION}} run: | - # Make the script executable - chmod +x ./update-version.sh - - # Check if README version matches tag version - # The script will exit with 0 if versions match, 1 if they don't - if ./update-version.sh --check "${{ steps.tag.outputs.MODULE_NAME }}" "${{ steps.tag.outputs.VERSION }}"; then + if ./update-version.sh --check $MODULE_NAME $VERSION echo "NEEDS_UPDATE=false" >> $GITHUB_OUTPUT echo "README version already matches tag version - no update needed" else echo "NEEDS_UPDATE=true" >> $GITHUB_OUTPUT echo "README version doesn't match tag version - update needed" fi - + # Update README with new version - name: Update README version if: steps.check.outputs.NEEDS_UPDATE == 'true' + env: + MODULE_NAME: ${{steps.tag.outputs.MODULE_NAME}} + VERSION: ${{steps.tag.outputs.VERSION}} run: | # Set git identity for commits git config user.name "cdrci" - git config user.email "cdrci@users.noreply.github.com" - + git config user.email "78873720+cdrci@users.noreply.github.com" + # Update the README with the new version - chmod +x ./update-version.sh - ./update-version.sh "${{ steps.tag.outputs.MODULE_NAME }}" "${{ steps.tag.outputs.VERSION }}" - echo "Updated README version to ${{ steps.tag.outputs.VERSION }}" - - # Create PR with the changes + ./update-version.sh $MODULE_NAME $VERSION + echo "Updated README version of $MODULE_NAME to $VERSION" + - name: Create PR for version update - if: steps.check.outputs.NEEDS_UPDATE == 'true' + if: steps.check.outputs.NEEDS_UPDATE == 'true' && github.repository_owner == 'coder' id: create-pr env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + MODULE_NAME: ${{steps.tag.outputs.MODULE_NAME}} + VERSION: ${{steps.tag.outputs.VERSION}} + TAG: ${{steps.tag.outputs.TAG}} run: | - # Set variables for PR creation - MODULE="${{ steps.tag.outputs.MODULE_NAME }}" - VERSION="${{ steps.tag.outputs.VERSION }}" - BRANCH="automated-update-$MODULE-$VERSION" - PR_TITLE="chore: update $MODULE version to $VERSION" - - # Create a branch for the PR + BRANCH="auto-update-$MODULE_NAME-$VERSION" + PR_TITLE="chore($MODULE_NAME): update version to $VERSION" git checkout -b "$BRANCH" - - # Commit the changes - git add "$MODULE/README.md" + git add "$MODULE_NAME/README.md" git commit -m "$PR_TITLE" - - # Push the branch to the repository git push origin "$BRANCH" - - # Create a PR using GitHub CLI + PR_URL=$(gh pr create \ --title "$PR_TITLE" \ - --body "Updates README version to match tag ${{ steps.tag.outputs.TAG_NAME }}" \ + --body "Updates module version to match the latest tag $TAG" \ --base main \ --head "$BRANCH") - - echo "Created PR: $PR_URL" - - # Extract PR number from the URL - PR_NUMBER=$(echo "$PR_URL" | grep -o '[0-9]*$') - echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT - - # Enable auto-merge for the PR - gh pr merge "$PR_NUMBER" --auto --squash - echo "Enabled auto-merge for PR #$PR_NUMBER" - - # Auto-approve the PR - - name: Auto-approve PR - if: steps.create-pr.outputs.pr_number - uses: hmarr/auto-approve-action@v3 - with: - pull-request-number: ${{ steps.create-pr.outputs.pr_number }} - github-token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + + gh pr merge "$PR_URL" --auto --squash + echo "Enabled auto-merge for $PR_URL" + + # TODO: Add Autoapprove PR diff --git a/release.sh b/release.sh index 62834e32..08e56e36 100755 --- a/release.sh +++ b/release.sh @@ -3,53 +3,85 @@ # release.sh - Creates annotated tags for module releases # # This script is used by maintainers to create annotated tags for module releases. -# It supports two main modes: +# It supports three main modes: # 1. Creating a new tag for a module: ./release.sh module-name X.Y.Z -# 2. Listing all modules with their versions: ./release.sh --list +# 2. Creating and pushing a new tag for a module: ./release.sh module-name X.Y.Z --push +# 3. Listing all modules with their versions: ./release.sh --list # # When a tag is pushed, it triggers a GitHub workflow that updates README versions. set -euo pipefail -# Handle --list option to show all modules and their versions -if [[ "$#" -eq 1 && "$1" == "--list" ]]; then - # Function to extract version from README - extract_version() { - grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$1" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" - } +# Function to extract version from README +extract_version() { + grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$1" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" +} + +# Parse command line options +LIST=false +DRY_RUN=false +PUSH=false +TEMP=$(getopt -o 'ldp' --long 'list,dry-run,push' -n 'release.sh' -- "$@") +eval set -- "$TEMP" +while true; do + case "$1" in + -l|--list) + LIST=true + shift + ;; + -d|--dry-run) + DRY_RUN=true + shift + ;; + -p|--push) + PUSH=true + shift + ;; + --) + shift + break + ;; + *) + echo "Internal error!" + exit 1 + ;; + esac +done + +# Handle listing all modules and their versions +if [[ "$LIST" == "true" ]]; then # Display header for module listing echo "Listing all modules and their latest versions:" - echo "--------------------------------------------------" + echo "----------------------------------------------------------" printf "%-30s %-15s %s\n" "MODULE" "README VERSION" "LATEST TAG" - echo "--------------------------------------------------" - - # Loop through all directories that look like modules + echo "----------------------------------------------------------" + + # Loop through all module directories for dir in */; do if [[ -d "$dir" && -f "${dir}README.md" && "$dir" != ".git/" ]]; then module_name="${dir%/}" - # Get version from README + + # Get README version readme_version=$(extract_version "${dir}README.md") + # Get latest tag for this module latest_tag=$(git tag -l "release/${module_name}/v*" | sort -V | tail -n 1) - tag_version=$([ -n "$latest_tag" ] && echo "$latest_tag" | sed 's|release/'"${module_name}"'/v||' || echo "none") + + # Set tag version with parameter expansion and default value + tag_version=${latest_tag:+${latest_tag#release/${module_name}/v}} + tag_version=${tag_version:-none} + # Display module info printf "%-30s %-15s %s\n" "$module_name" "$readme_version" "$tag_version" fi done - - echo "--------------------------------------------------" - exit 0 -fi -# Handle --dry-run option -DRY_RUN=false -if [[ "$1" == "--dry-run" ]]; then - DRY_RUN=true - shift + echo "----------------------------------------------------------" + exit 0 fi -# Validate arguments +# Validate arguments for module release if [[ "$#" -ne 2 ]]; then echo "Usage: ./release.sh [--dry-run] module-name X.Y.Z" echo " or: ./release.sh --list" @@ -65,11 +97,6 @@ if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then exit 1 fi -# Function to extract version from README -extract_version() { - grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$1" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" -} - # Check if module exists if [[ ! -d "$MODULE_NAME" || ! -f "$MODULE_NAME/README.md" ]]; then echo "Error: Module directory not found or missing README.md" @@ -96,15 +123,13 @@ echo "Tag name: $TAG_NAME" if [[ "$DRY_RUN" == "false" ]]; then # Create annotated tag git tag -a "$TAG_NAME" -m "Release $MODULE_NAME v$VERSION" - echo "Success! Tag '$TAG_NAME' created." - echo "To complete the release: git push origin $TAG_NAME" - echo "" - echo "When pushed, this will trigger the GitHub Action to:" - echo "- Update the README.md version" - echo "- Create a PR with the update" - echo "- Auto-approve and merge the PR" + echo "Tag '$TAG_NAME' created." + if [[ "$PUSH" == "true" ]]; then + git push origin "$TAG_NAME" + echo "Success! Tag '$TAG_NAME' pushed to remote." + fi else echo "[DRY RUN] Would create tag: $TAG_NAME" fi -exit 0 \ No newline at end of file +exit 0 diff --git a/update-version.sh b/update-version.sh index 36ff4c79..50271a46 100755 --- a/update-version.sh +++ b/update-version.sh @@ -1,14 +1,28 @@ #!/usr/bin/env bash # -# update-version.sh - Updates or checks README.md version -# -# This script is used for two main purposes: -# 1. Update the version in a module's README.md file (normal mode) -# 2. Check if the version in README.md matches a specified version (--check mode) -# -# It's primarily used by the GitHub Actions workflow that runs when tags are pushed. +# update-version.sh - Updates or checks README.md version in module documentation + +set -eo pipefail -set -euo pipefail +# Display help message +show_help() { + echo "Usage: ./update-version.sh [--check|--help] MODULE_NAME VERSION" + echo + echo "Options:" + echo " --check Check if README.md version matches VERSION without updating" + echo " --help Display this help message and exit" + echo + echo "Examples:" + echo " ./update-version.sh code-server 1.2.3 # Update version in code-server/README.md" + echo " ./update-version.sh --check code-server 1.2.3 # Check if version matches 1.2.3" + echo +} + +# Handle help request +if [[ $# -eq 0 || "$1" == "--help" ]]; then + show_help + exit 0 +fi # Check if we're in check-only mode CHECK_ONLY=false @@ -19,7 +33,10 @@ fi # Validate we have the right number of arguments if [[ "$#" -ne 2 ]]; then - echo "Usage: ./update-version.sh [--check] module-name X.Y.Z" + echo "Error: Incorrect number of arguments" + echo "Expected exactly 2 arguments (MODULE_NAME VERSION)" + echo + show_help exit 1 fi @@ -28,27 +45,35 @@ VERSION="$2" # Validate version format (X.Y.Z) if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "Error: Version must be in format X.Y.Z" + echo "Error: Version must be in format X.Y.Z (e.g., 1.2.3)" exit 1 fi # Check if module directory exists -if [[ ! -d "$MODULE_NAME" || ! -f "$MODULE_NAME/README.md" ]]; then - echo "Error: Module directory not found or missing README.md" +if [[ ! -d "$MODULE_NAME" ]]; then + echo "Error: Module directory '$MODULE_NAME' not found" + echo "Available modules:" + find . -type d -mindepth 1 -maxdepth 1 -not -path "*/\.*" | sed 's|^./||' | sort + exit 1 +fi + +# Check if README.md exists +if [[ ! -f "$MODULE_NAME/README.md" ]]; then + echo "Error: README.md not found in '$MODULE_NAME' directory" exit 1 fi # Extract version from README.md file extract_version() { - # This finds version lines like: version = "1.2.3" grep -o 'version *= *"[0-9]\+\.[0-9]\+\.[0-9]\+"' "$1" | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0" } # Update version in README.md file update_version() { - local tmpfile=$(mktemp) - # This awk script finds and updates version lines in code blocks - # It's careful to only update version lines in the right context (not in nested blocks) + local file="$1" latest_tag=$2 tmpfile + tmpfile=$(mktemp) + echo "Updating version in $file from $(extract_version "$file") to $latest_tag..." + awk -v tag="$2" ' BEGIN { in_code_block = 0; in_nested_block = 0 } { @@ -57,7 +82,7 @@ update_version() { in_code_block = !in_code_block if (!in_code_block) { in_nested_block = 0 } } - + # Inside code blocks, track nested {} blocks if (in_code_block) { if ($0 ~ /{/ && !($1 == "module" || $1 ~ /^[a-zA-Z0-9_]+$/)) { @@ -66,7 +91,7 @@ update_version() { if ($0 ~ /}/ && in_nested_block > 0) { in_nested_block-- } - + # Only update version if not in a nested block if (!in_nested_block && $1 == "version" && $2 == "=") { sub(/"[^"]*"/, "\"" tag "\"") @@ -83,10 +108,12 @@ README_VERSION=$(extract_version "$README_PATH") # In check mode, just return success/failure based on version match if [[ "$CHECK_ONLY" == "true" ]]; then if [[ "$README_VERSION" == "$VERSION" ]]; then - # Success: versions match + echo "✅ Success: Version in $README_PATH matches $VERSION" exit 0 else - # Failure: versions don't match + echo "❌ Error: Version mismatch in $README_PATH" + echo "Expected: $VERSION" + echo "Found: $README_VERSION" exit 1 fi fi @@ -94,6 +121,9 @@ fi # Update the version if needed if [[ "$README_VERSION" != "$VERSION" ]]; then update_version "$README_PATH" "$VERSION" + echo "✅ Version updated successfully to $VERSION" +else + echo "ℹ️ Version in $README_PATH already set to $VERSION, no update needed" fi -exit 0 \ No newline at end of file +exit 0 From 68f5396e5ddb5b80a6d9a54598e73bf7a9c529db Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Tue, 15 Apr 2025 13:34:16 +0000 Subject: [PATCH 31/31] Rename update-version.sh to update_version.sh and improve docs --- .github/workflows/update-readme-version.yaml | 4 +- CONTRIBUTING.md | 66 +++++++++++--------- package.json | 2 +- release.sh | 8 +-- update-version.sh => update_version.sh | 0 5 files changed, 44 insertions(+), 36 deletions(-) rename update-version.sh => update_version.sh (100%) diff --git a/.github/workflows/update-readme-version.yaml b/.github/workflows/update-readme-version.yaml index 9929be7d..83a2c410 100644 --- a/.github/workflows/update-readme-version.yaml +++ b/.github/workflows/update-readme-version.yaml @@ -47,7 +47,7 @@ jobs: MODULE_NAME: ${{steps.tag.outputs.MODULE_NAME}} VERSION: ${{steps.tag.outputs.VERSION}} run: | - if ./update-version.sh --check $MODULE_NAME $VERSION + if ./update_version.sh --check $MODULE_NAME $VERSION echo "NEEDS_UPDATE=false" >> $GITHUB_OUTPUT echo "README version already matches tag version - no update needed" else @@ -67,7 +67,7 @@ jobs: git config user.email "78873720+cdrci@users.noreply.github.com" # Update the README with the new version - ./update-version.sh $MODULE_NAME $VERSION + ./update_version.sh $MODULE_NAME $VERSION echo "Updated README version of $MODULE_NAME to $VERSION" - name: Create PR for version update diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c2971a16..940c840e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,7 +22,8 @@ Follow the instructions to ensure that Bun is available globally. Once Bun has b ## Testing a Module -> **Note:** It is the responsibility of the module author to implement tests for their module. The author must test the module locally before submitting a PR. +> [!NOTE] +> It is the responsibility of the module author to implement tests for their module. The author must test the module locally before submitting a PR. A suite of test-helpers exists to run `terraform apply` on modules with variables, and test script output against containers. @@ -53,45 +54,52 @@ module "example" { ## Releases -> [!WARNING] -> When creating a new release, make sure that your new version number is fully accurate. If a version number is incorrect or does not exist, we may end up serving incorrect/old data for our various tools and providers. +The release process is automated with these steps: + +## 1. Create and Merge PR + +- Create a PR with your module changes +- Get your PR reviewed, approved, and merged to `main` + +## 2. Prepare Release (Maintainer Task) + +After merging to main, a maintainer will: -The release process is automated and follows these steps: +- View all modules and their current versions: -1. Create a PR with your module changes + ```shell + ./release.sh --list + ``` - - You **do not** need to update the version number in the README.md file - - Focus on implementing your feature or fix +- Determine the next version number based on changes: -2. Have your PR reviewed, approved, and merged to main + - **Patch version** (1.2.3 → 1.2.4): Bug fixes + - **Minor version** (1.2.3 → 1.3.0): New features, adding inputs, deprecating inputs + - **Major version** (1.2.3 → 2.0.0): Breaking changes (removing inputs, changing input types) -3. After merging to main, a maintainer will: +- Create and push an annotated tag: - - Create and push an annotated tag with an appropriate version based on your changes: + ```shell + # Fetch latest changes + git fetch origin + + # Create and push tag + ./release.sh module-name 1.2.3 --push + ``` - ```shell - # Create an annotated tag with an exact version number - ./release.sh module-name 1.2.3 - - # Push the tag to the repository - git push origin release/module-name/v1.2.3 - ``` + The tag format will be: `release/module-name/v1.0.0` - - View all modules and their current versions with: +## 3. Automated Version Update - ```shell - ./release.sh --list - ``` +When the tag is pushed, a GitHub Action automatically: - - The tag will follow the format: `release/module-name/v1.0.0` +- Checks if the module's `README.md` version matches the tag version +- Updates the `README.md` version if needed +- Creates a PR with the version update -4. When the tag is pushed, a GitHub Action will automatically: - - Update the module's README.md version to match the tag - - Create a PR with the version update by github-actions[bot] - - Auto-approve and auto-merge the version update PR - - No manual action required - the version will be updated automatically +## 4. Publishing to Registry -Following that, our automated processes will handle publishing new data to [`registry.coder.com`](https://registry.coder.com): +Our automated processes will handle publishing new data to [registry.coder.com](https://registry.coder.com). > [!NOTE] -> Some data in `registry.coder.com` is fetched on demand from the Module repo's main branch. This data should be updated almost immediately after a new release, but other changes will take some time to propagate. +> Some data in registry.coder.com is fetched on demand from the [coder/modules](https://github.com/coder/modules) repo's `main` branch. This data should update almost immediately after a release, while other changes will take some time to propagate. diff --git a/package.json b/package.json index 873ac51b..a122f4f2 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "modules", "scripts": { "test": "bun test", - "fmt": "bun x prettier -w **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt **/*.tf .sample/main.tf", + "fmt": "bun x prettier -w **/*.sh .sample/run.sh new.sh terraform_validate.sh release.sh update_version.sh **/*.ts **/*.md *.md && terraform fmt **/*.tf .sample/main.tf", "fmt:ci": "bun x prettier --check **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt -check **/*.tf .sample/main.tf", "lint": "bun run lint.ts && ./terraform_validate.sh" }, diff --git a/release.sh b/release.sh index 08e56e36..a5a5b11d 100755 --- a/release.sh +++ b/release.sh @@ -26,15 +26,15 @@ eval set -- "$TEMP" while true; do case "$1" in - -l|--list) + -l | --list) LIST=true shift ;; - -d|--dry-run) + -d | --dry-run) DRY_RUN=true shift ;; - -p|--push) + -p | --push) PUSH=true shift ;; @@ -108,7 +108,7 @@ README_VERSION=$(extract_version "$MODULE_NAME/README.md") TAG_NAME="release/$MODULE_NAME/v$VERSION" # Check if tag already exists -if git rev-parse -q --verify "refs/tags/$TAG_NAME" >/dev/null; then +if git rev-parse -q --verify "refs/tags/$TAG_NAME" > /dev/null; then echo "Error: Tag $TAG_NAME already exists" exit 1 fi diff --git a/update-version.sh b/update_version.sh similarity index 100% rename from update-version.sh rename to update_version.sh