Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 148 additions & 0 deletions .github/workflows/pr-version-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
name: PR Version Check

on:
pull_request:
branches:
- main
types: [opened, synchronize, reopened, ready_for_review]

permissions:
contents: read
pull-requests: write

jobs:
check_version_bump:
runs-on: ubuntu-latest
steps:
- name: Checkout PR branch
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Auth GH CLI
run: gh auth setup-git
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Check Chart.yaml version bump
id: version_check
run: |
set -euo pipefail

# Get current version from PR's Chart.yaml
if [ ! -f "Chart.yaml" ]; then
echo "❌ Chart.yaml not found"
exit 1
fi

pr_version=$(grep '^version:' Chart.yaml | awk '{print $2}')
echo "📄 PR Chart.yaml version: $pr_version"

# Get latest release/tag version
latest_tag=$(gh api repos/${{ github.repository }}/tags --jq '.[0].name' 2>/dev/null || echo "")

if [ -z "$latest_tag" ]; then
echo "ℹ️ No existing releases found"
echo "✅ This will be the first release with version: $pr_version"
echo "status=success" >> $GITHUB_OUTPUT
echo "message=✅ First release - version $pr_version will be used" >> $GITHUB_OUTPUT
exit 0
fi

# Remove 'v' prefix and chart name prefix if present
# Handles both "v0.1.32" and "webrix-postgres-0.1.32" formats
latest_version=$(echo "$latest_tag" | sed -E 's/^v//;s/^[a-zA-Z-]+-//')
echo "📦 Latest release version: $latest_version"

# Compare versions
if [ "$pr_version" = "$latest_version" ]; then
echo "❌ Version not bumped!"
echo "status=failure" >> $GITHUB_OUTPUT
echo "message=❌ Chart.yaml version ($pr_version) must be bumped from latest release ($latest_version)" >> $GITHUB_OUTPUT
exit 1
fi

# Validate version is greater than latest
IFS='.' read -r pr_major pr_minor pr_patch <<< "$pr_version"
IFS='.' read -r latest_major latest_minor latest_patch <<< "$latest_version"

# Remove any non-numeric suffixes (e.g., -alpha, -beta)
pr_major=${pr_major%%[^0-9]*}
pr_minor=${pr_minor%%[^0-9]*}
pr_patch=${pr_patch%%[^0-9]*}
latest_major=${latest_major%%[^0-9]*}
latest_minor=${latest_minor%%[^0-9]*}
latest_patch=${latest_patch%%[^0-9]*}

version_greater=false

if [ "$pr_major" -gt "$latest_major" ]; then
version_greater=true
bump_type="major"
elif [ "$pr_major" -eq "$latest_major" ] && [ "$pr_minor" -gt "$latest_minor" ]; then
version_greater=true
bump_type="minor"
elif [ "$pr_major" -eq "$latest_major" ] && [ "$pr_minor" -eq "$latest_minor" ] && [ "$pr_patch" -gt "$latest_patch" ]; then
version_greater=true
bump_type="patch"
fi

if [ "$version_greater" = false ]; then
echo "❌ Version is not greater than latest release!"
echo "status=failure" >> $GITHUB_OUTPUT
echo "message=❌ Chart.yaml version ($pr_version) must be greater than latest release ($latest_version)" >> $GITHUB_OUTPUT
exit 1
fi

echo "✅ Version bump detected: $latest_version → $pr_version ($bump_type)"
echo "status=success" >> $GITHUB_OUTPUT
echo "message=✅ Version bumped: $latest_version → $pr_version ($bump_type)" >> $GITHUB_OUTPUT
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Comment on PR
if: always() && github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const status = '${{ steps.version_check.outputs.status }}';
const message = '${{ steps.version_check.outputs.message }}';

const commentBody = status === 'success'
? `## ✅ Version Check Passed\n\n${message}\n\nThis PR can be merged.`
: `## ❌ Version Check Failed\n\n${message}\n\n### Required Action\n\nPlease update the \`version\` field in \`Chart.yaml\` to be greater than the latest release.\n\n**Tip**: Use semantic versioning:\n- **Patch** (x.y.Z): Bug fixes, small changes\n- **Minor** (x.Y.0): New features, backward compatible\n- **Major** (X.0.0): Breaking changes`;

// Find existing bot comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});

const botComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('Version Check')
);

// Update or create comment
if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: commentBody
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: commentBody
});
}

- name: Set check status
if: steps.version_check.outputs.status == 'failure'
run: |
echo "::error::Chart.yaml version must be bumped before merging"
exit 1
56 changes: 49 additions & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ jobs:
run: |
chart_name=$(grep '^name:' Chart.yaml | awk '{print $2}')
chart_version=$(grep '^version:' Chart.yaml | awk '{print $2}')

echo "📋 Chart: $chart_name"
echo "📦 Version: $chart_version"

echo "name=$chart_name" >> $GITHUB_OUTPUT
echo "version=$chart_version" >> $GITHUB_OUTPUT

Expand All @@ -57,9 +57,16 @@ jobs:
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Helm Lint
- name: Build chart dependencies
if: steps.check_release.outputs.exists == 'false'
run: helm lint .
run: |
echo "🔨 Building chart dependencies..."
if [ -f "Chart.lock" ]; then
helm dependency build
echo "✅ Dependencies built"
else
echo "ℹ️ No dependencies to build"
fi

- name: Package Helm chart
if: steps.check_release.outputs.exists == 'false'
Expand All @@ -68,6 +75,7 @@ jobs:
mkdir -p .cr-release-packages
helm package . --destination .cr-release-packages
echo "✅ Chart packaged"
ls -lh .cr-release-packages/

- name: Create GitHub Release
if: steps.check_release.outputs.exists == 'false'
Expand All @@ -94,21 +102,34 @@ jobs:
git add index.yaml
git commit -m "Initialize gh-pages"
fi
# Clean up the package directory from the previous branch
rm -rf .cr-release-packages

- name: Update Helm repository index
if: steps.check_release.outputs.exists == 'false'
run: |
echo "📝 Updating repository index..."

# Download the packaged chart from the release
mkdir -p .cr-release-packages
gh release download "v${{ steps.chart_version.outputs.version }}" \
--pattern "*.tgz" \
--dir .cr-release-packages


# Move the chart to root for indexing (so URL doesn't include .cr-release-packages/)
mv .cr-release-packages/*.tgz .
helm repo index . --url https://github.com/${{ github.repository }}/releases/download/v${{ steps.chart_version.outputs.version }} --merge index.yaml


# Generate/update index.yaml (only use --merge if index.yaml is non-empty)
if [ -s index.yaml ]; then
helm repo index . --url https://github.com/${{ github.repository }}/releases/download/v${{ steps.chart_version.outputs.version }} --merge index.yaml
else
helm repo index . --url https://github.com/${{ github.repository }}/releases/download/v${{ steps.chart_version.outputs.version }}
fi

# Clean up the .tgz file (we don't need it in gh-pages, it's in the GitHub release)
rm -f *.tgz
rm -rf .cr-release-packages

echo "✅ Index updated"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -120,3 +141,24 @@ jobs:
git commit -m "Update index for v${{ steps.chart_version.outputs.version }}"
git push origin gh-pages
echo "✅ Index pushed to gh-pages"

- name: Release summary
run: |
if [ "${{ steps.check_release.outputs.exists }}" == "true" ]; then
echo "## ℹ️ Release Already Exists" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Version **v${{ steps.chart_version.outputs.version }}** was already released." >> $GITHUB_STEP_SUMMARY
else
echo "## 🎉 Helm Chart Released!" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Chart:** ${{ steps.chart_version.outputs.name }}" >> $GITHUB_STEP_SUMMARY
echo "**Version:** v${{ steps.chart_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
echo "**Repository:** https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 📦 Installation" >> $GITHUB_STEP_SUMMARY
echo '```bash' >> $GITHUB_STEP_SUMMARY
echo "helm repo add ${{ steps.chart_version.outputs.name }} https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}" >> $GITHUB_STEP_SUMMARY
echo "helm repo update" >> $GITHUB_STEP_SUMMARY
echo "helm install my-release ${{ steps.chart_version.outputs.name }}/${{ steps.chart_version.outputs.name }}" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
fi
2 changes: 2 additions & 0 deletions templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else if contains .Release.Name $name }}
{{- $name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
Comment on lines 16 to 22
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Fullname collision risk 🐞 Bug ⛯ Reliability

postgresql.fullname can now return the bare chart name when the release name is a substring of the
chart name, which can cause multiple releases in the same namespace to generate identical resource
names. This can lead to install/upgrade failures and cross-release resource collisions for
StatefulSet/Secret/NetworkPolicy names that use postgresql.fullname.
Agent Prompt
### Issue description
`postgresql.fullname` may return the chart name without the release name when the release name is a substring of the chart name. Since many resources use `postgresql.fullname` for `metadata.name`, this can create cross-release naming collisions and break installs/upgrades.

### Issue Context
The added branch:
- triggers when `contains .Release.Name $name` (i.e., `$name` contains the release name)
- returns `$name` only

### Fix Focus Areas
- templates/_helpers.tpl[12-23]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

{{- end }}
Expand Down
2 changes: 1 addition & 1 deletion templates/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "postgresql.primary.svcName" . }}
name: {{ .Release.Name }}-postgresql
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Service name mismatch 🐞 Bug ✓ Correctness

The primary Service is renamed to {{ .Release.Name }}-postgresql, but NOTES.txt (and the
existing postgresql.primary.svcName helper) still point users to a different service name derived
from postgresql.fullname. This will cause the documented DNS/psql/port-forward commands to fail
and also bypass nameOverride/fullnameOverride for the Service name.
Agent Prompt
### Issue description
The primary Service name is hard-coded to `{{ .Release.Name }}-postgresql`, but the chart’s helper (`postgresql.primary.svcName`) and `NOTES.txt` still reference a different name derived from `postgresql.fullname`. This breaks the documented connection instructions and makes naming overrides inconsistent.

### Issue Context
- `templates/service.yaml` uses a hard-coded name.
- `templates/NOTES.txt` uses `postgresql.primary.svcName`.
- `postgresql.primary.svcName` resolves to `postgresql.fullname`.

### Fix Focus Areas
- templates/service.yaml[1-8]
- templates/NOTES.txt[5-8]
- templates/_helpers.tpl[150-159]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "postgresql.labels" . | nindent 4 }}
Expand Down
Loading