diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 57f3bb0..a25748a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,9 +51,13 @@ jobs: - name: Get changed codemods id: codemods run: | - dirs=$(git diff --name-only origin/main...HEAD -- 'codemods/' \ - | awk -F/ 'NF>=3 {print $1"/"$2"/"$3}' | sort -u | tr '\n' ' ') - echo "dirs=$dirs" >> "$GITHUB_OUTPUT" + candidates=$(git diff --name-only origin/main...HEAD -- 'codemods/' \ + | awk -F/ 'NF>=3 {print $1"/"$2"/"$3}' | sort -u) + dirs="" + for d in $candidates; do + [ -f "$d/package.json" ] && dirs="$dirs $d" + done + echo "dirs=$(echo $dirs | xargs)" >> "$GITHUB_OUTPUT" - name: Format check (changed files) if: steps.changed.outputs.files != '' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9a3d801..089b759 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -70,10 +70,10 @@ The manual `Publish Codemod (Manual)` workflow (`.github/workflows/publish.yml`) ## Adding a new codemod -Each codemod lives in its own directory under `codemods///`: +Each codemod lives in its own directory under `codemods///`: ``` -codemods/// +codemods/// scripts/codemod.ts # Codemod logic (jssg / ast-grep) tests/ # Input/expected test fixtures codemod.yaml # Codemod manifest (version is auto-synced) @@ -81,6 +81,8 @@ codemods/// package.json # Source of truth for name + version ``` +The `` is either a Backstage release version (e.g. `v1.52.0`) for migration codemods, or `misc` for codemods not tied to a specific release (e.g. NFS migration). + Conventions to follow: - The two-level glob `codemods/*/*/` is assumed by `scripts/sync-codemod-versions.sh` and `scripts/tag-and-publish.sh`. Don't flatten or deepen this layout. diff --git a/codemods/misc/.gitkeep b/codemods/misc/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/scripts/generate-readme-codemods.sh b/scripts/generate-readme-codemods.sh index 6f997b4..6ba8e30 100644 --- a/scripts/generate-readme-codemods.sh +++ b/scripts/generate-readme-codemods.sh @@ -16,20 +16,25 @@ CODEMODS_DIR="$REPO_ROOT/codemods" START_MARKER="" END_MARKER="" -# Render a version table -render_version() { - local version="$1" - local version_dir="$CODEMODS_DIR/$version" +# Render a table for a group of codemods +render_group() { + local group="$1" + local group_dir="$CODEMODS_DIR/$group" - echo "### $version" - echo "" - # shellcheck disable=SC2016 - echo "Run the [\`migration-recipe\`](./codemods/$version/migration-recipe) to apply every codemod below in one pass, or run any individual codemod on its own." + echo "### $group" echo "" + + # Only show migration-recipe link for version directories that have one + if [ -d "$group_dir/migration-recipe" ]; then + # shellcheck disable=SC2016 + echo "Run the [\`migration-recipe\`](./codemods/$group/migration-recipe) to apply every codemod below in one pass, or run any individual codemod on its own." + echo "" + fi + echo "| Codemod | Description |" echo "| ------- | ----------- |" - for codemod_dir in "$version_dir"/*/; do + for codemod_dir in "$group_dir"/*/; do local name name=$(basename "$codemod_dir") local yaml="$codemod_dir/codemod.yaml" @@ -40,15 +45,18 @@ render_version() { # Strip "Backstage X.Y.Z: " prefix — the version header already shows it desc=$(echo "$desc" | sed 's/^Backstage [0-9.]*: *//') - echo "| [$name](./codemods/$version/$name) | $desc |" + echo "| [$name](./codemods/$group/$name) | $desc |" done echo "" } -# Collect all versions (newest first), show only latest 2 -mapfile -t all_versions < <(ls "$CODEMODS_DIR" | sort -Vr) -total=${#all_versions[@]} +# Separate version directories (v*) from non-version groups (misc, etc.) +mapfile -t version_dirs < <(ls "$CODEMODS_DIR" | grep '^v' | sort -Vr) +mapfile -t other_dirs < <(ls "$CODEMODS_DIR" | grep -v '^v' | grep -v '^\.gitkeep$' | sort) + +# Show latest 2 versions +total=${#version_dirs[@]} show=2 if [ "$total" -lt "$show" ]; then show=$total @@ -56,8 +64,8 @@ fi # Build the section section="" -for version in "${all_versions[@]:0:$show}"; do - section+=$(render_version "$version") +for version in "${version_dirs[@]:0:$show}"; do + section+=$(render_group "$version") section+=$'\n' done @@ -65,6 +73,17 @@ if [ "$total" -gt "$show" ]; then section+="Older versions are available in the [\`codemods/\`](./codemods) directory."$'\n\n' fi +# Append non-version groups (misc, etc.) if they contain any codemods +for group in "${other_dirs[@]}"; do + local_dir="$CODEMODS_DIR/$group" + # Skip empty groups (only .gitkeep) — count subdirectories with codemod.yaml + codemod_count=$(find "$local_dir" -mindepth 2 -maxdepth 2 -name 'codemod.yaml' 2>/dev/null | head -1 || true) + if [ -n "$codemod_count" ]; then + section+=$(render_group "$group") + section+=$'\n' + fi +done + # Check markers exist if ! grep -q "$START_MARKER" "$README"; then echo "ERROR: $START_MARKER not found in README.md" @@ -86,4 +105,4 @@ mv "$README.tmp" "$README" # Format so the committed output matches what prettier expects yarn format "$README" >/dev/null 2>&1 || true -echo "✅ README.md updated with ${all_versions[0]} and ${all_versions[1]} ($total total on disk)" +echo "✅ README.md updated with ${version_dirs[0]} and ${version_dirs[1]} ($total versions on disk)"