-
Notifications
You must be signed in to change notification settings - Fork 1.2k
fix: prevent Node.js upgrade workflow from creating PRs with empty versions #4055
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
… The Node.js upgrade workflow was creating broken PRs with empty version numbers due to incorrect tag format assumptions and lack of validation. ## Root Cause - Alpine nodejs releases use 'vX.Y.Z' format, not 'nodeXX-X.Y.Z' format - No validation prevented empty/invalid versions from being used - Silent failures when grep patterns didn't match expected formats ## Changes Made 1. **Fix tag format patterns**: - Change from '^node20-' to '^v20\.' patterns - Change from '^node24-' to '^v24\.' patterns - Correctly extract versions with 'sed s/^v//' instead of 's/^node20-//' 2. **Add comprehensive validation**: - Validate versions are not empty after API calls - Validate versions match x.y.z format using regex '^[0-9]+\.[0-9]+\.[0-9]+$' - Multiple validation checkpoints throughout the workflow - Final validation before creating PR to prevent invalid updates 3. **Improve error handling**: - Display available releases for debugging when validation fails - Clear error messages with actionable information - Fail fast instead of creating broken PRs - Verify file updates were applied correctly 4. **Enhance PR creation**: - Use validated variables instead of GitHub outputs in commit messages - Remove single quotes from here-doc to allow variable expansion - Better verification of sed command results ## Impact - Eliminates invalid PRs with empty version numbers - Future-proof against upstream tag format changes - Better debugging information when issues occur - Maintains data integrity in externals.sh Fixes: Node.js upgrade PRs showing "Node 20: 20.19.5 → (empty)"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes a broken automated Node.js upgrade workflow that was creating PRs with empty version strings due to incorrect release tag pattern matching. The workflow was looking for node20-X.Y.Z format tags but the alpine_nodejs repository actually uses vX.Y.Z format.
Key changes:
- Fixed grep patterns to match actual alpine_nodejs release tag format (
^vX.Y.Zinstead of^nodeX-) - Added comprehensive validation to prevent empty or malformed version strings
- Enhanced error handling with better diagnostics when version detection fails
| if [ -z "$LATEST_NODE20" ] || [ "$LATEST_NODE20" = "" ]; then | ||
| echo "::error title=Invalid Node 20 Version::Failed to determine valid Node 20 version. Got: '$LATEST_NODE20'" | ||
| echo "Available alpine_nodejs releases:" | ||
| echo "$ALPINE_RELEASES" | head -10 | ||
| exit 1 | ||
| fi | ||
| if [ -z "$LATEST_NODE24" ] || [ "$LATEST_NODE24" = "" ]; then |
Copilot
AI
Sep 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The condition [ -z \"$LATEST_NODE20\" ] || [ \"$LATEST_NODE20\" = \"\" ] is redundant. The -z test already checks for empty strings, so the || [ \"$LATEST_NODE20\" = \"\" ] part is unnecessary and can be removed.
| if [ -z "$LATEST_NODE20" ] || [ "$LATEST_NODE20" = "" ]; then | |
| echo "::error title=Invalid Node 20 Version::Failed to determine valid Node 20 version. Got: '$LATEST_NODE20'" | |
| echo "Available alpine_nodejs releases:" | |
| echo "$ALPINE_RELEASES" | head -10 | |
| exit 1 | |
| fi | |
| if [ -z "$LATEST_NODE24" ] || [ "$LATEST_NODE24" = "" ]; then | |
| if [ -z "$LATEST_NODE20" ]; then | |
| echo "::error title=Invalid Node 20 Version::Failed to determine valid Node 20 version. Got: '$LATEST_NODE20'" | |
| echo "Available alpine_nodejs releases:" | |
| echo "$ALPINE_RELEASES" | head -10 | |
| exit 1 | |
| fi | |
| if [ -z "$LATEST_NODE24" ]; then |
| if [ -z "$LATEST_NODE20" ] || [ "$LATEST_NODE20" = "" ]; then | ||
| echo "::error title=Invalid Node 20 Version::Failed to determine valid Node 20 version. Got: '$LATEST_NODE20'" | ||
| echo "Available alpine_nodejs releases:" | ||
| echo "$ALPINE_RELEASES" | head -10 | ||
| exit 1 | ||
| fi | ||
| if [ -z "$LATEST_NODE24" ] || [ "$LATEST_NODE24" = "" ]; then |
Copilot
AI
Sep 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The condition [ -z \"$LATEST_NODE24\" ] || [ \"$LATEST_NODE24\" = \"\" ] is redundant. The -z test already checks for empty strings, so the || [ \"$LATEST_NODE24\" = \"\" ] part is unnecessary and can be removed.
| if [ -z "$LATEST_NODE20" ] || [ "$LATEST_NODE20" = "" ]; then | |
| echo "::error title=Invalid Node 20 Version::Failed to determine valid Node 20 version. Got: '$LATEST_NODE20'" | |
| echo "Available alpine_nodejs releases:" | |
| echo "$ALPINE_RELEASES" | head -10 | |
| exit 1 | |
| fi | |
| if [ -z "$LATEST_NODE24" ] || [ "$LATEST_NODE24" = "" ]; then | |
| if [ -z "$LATEST_NODE20" ]; then | |
| echo "::error title=Invalid Node 20 Version::Failed to determine valid Node 20 version. Got: '$LATEST_NODE20'" | |
| echo "Available alpine_nodejs releases:" | |
| echo "$ALPINE_RELEASES" | head -10 | |
| exit 1 | |
| fi | |
| if [ -z "$LATEST_NODE24" ]; then |
| # Create PR body using here-doc for proper formatting | ||
| cat > pr_body.txt << 'EOF' | ||
| cat > pr_body.txt << EOF | ||
| Automated Node.js version update: | ||
| - Node 20: ${{ steps.node-versions.outputs.current_node20 }} → ${{ steps.node-versions.outputs.latest_node20 }} | ||
| - Node 24: ${{ steps.node-versions.outputs.current_node24 }} → ${{ steps.node-versions.outputs.latest_node24 }} | ||
| - Node 20: ${{ steps.node-versions.outputs.current_node20 }} → $NODE20_VERSION | ||
| - Node 24: ${{ steps.node-versions.outputs.current_node24 }} → $NODE24_VERSION |
Copilot
AI
Sep 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changing from << 'EOF' to << EOF enables variable expansion in the heredoc, which is necessary for the variables to be substituted. However, this makes the heredoc vulnerable to shell injection if the variables contain special characters. Consider using proper escaping or validation of the variables before using them in the heredoc.
See below for a potential fix:
# Sanitize variables to prevent shell injection in heredoc
safe_NODE20_VERSION=$(printf '%s' "$NODE20_VERSION" | tr -d '\n' | sed 's/"/\\"/g')
safe_NODE24_VERSION=$(printf '%s' "$NODE24_VERSION" | tr -d '\n' | sed 's/"/\\"/g')
# Create PR body using here-doc for proper formatting
cat > pr_body.txt << EOF
Automated Node.js version update:
- Node 20: ${{ steps.node-versions.outputs.current_node20 }} → $safe_NODE20_VERSION
- Node 24: ${{ steps.node-versions.outputs.current_node24 }} → $safe_NODE24_VERSION
Fix broken Node.js upgrade workflow
The automated Node upgrade workflow has been creating useless PRs like this one: #4050
The problem was that it was looking for the wrong release tag format in the alpine_nodejs repo and ended up with empty version strings.
What was broken
The workflow assumed alpine_nodejs releases were tagged like
node20-20.19.5but they're actually justv20.19.5. So when it tried to fall back to alpine releases, the grep patterns failed and we got empty strings.Result: PRs showing "Node 20: 20.19.5 → " with nothing after the arrow.
What I fixed
^node20-to^v20\.which actually matches the real tagsTesting
Ran the grep patterns manually against the real alpine_nodejs releases and confirmed they work:
v20.19.5,v24.8.0etc. are correctly parsed to20.19.5,24.8.0This should prevent any more broken automation PRs and make debugging easier when things do go wrong.