1111 required : false
1212 type : boolean
1313 default : false
14+ chart :
15+ description : ' Specific chart to release (optional, e.g. "charts/my-chart")'
16+ required : false
17+ type : string
1418
1519concurrency :
1620 group : release
4852 username : ${{ github.actor }}
4953 password : ${{ secrets.GITHUB_TOKEN }}
5054
55+ - name : Update chart dependencies
56+ run : |
57+ set -euo pipefail
58+ echo "Updating dependencies for all charts..."
59+ for chart_dir in charts/*; do
60+ if [ -f "$chart_dir/Chart.yaml" ]; then
61+ echo "Processing $chart_dir..."
62+ if grep -q "^dependencies:" "$chart_dir/Chart.yaml"; then
63+ echo " → Updating dependencies for $chart_dir"
64+ helm dependency update "$chart_dir"
65+ else
66+ echo " → No dependencies found, skipping"
67+ fi
68+ fi
69+ done
70+
5171 - name : Run chart-releaser
5272 id : chart-releaser
5373 uses : helm/chart-releaser-action@cae68fefc6b5f367a0275617c9f83181ba54714f # v1.7.0
5676 env :
5777 CR_TOKEN : " ${{ secrets.GITHUB_TOKEN }}"
5878
79+ - name : Package manually specified chart
80+ if : ${{ github.event.inputs.chart != '' }}
81+ run : |
82+ set -euo pipefail
83+ CHART_DIR="${{ github.event.inputs.chart }}"
84+
85+ if [ ! -d "$CHART_DIR" ]; then
86+ echo "ERROR: Chart directory $CHART_DIR does not exist"
87+ exit 1
88+ fi
89+
90+ # Update dependencies if they exist
91+ if grep -q "^dependencies:" "$CHART_DIR/Chart.yaml"; then
92+ echo "Updating dependencies for $CHART_DIR..."
93+ helm dependency update "$CHART_DIR"
94+ fi
95+
96+ echo "Packaging chart from $CHART_DIR..."
97+ mkdir -p .cr-release-packages
98+ helm package "$CHART_DIR" --destination .cr-release-packages
99+
100+ echo "Packaged charts:"
101+ ls -lh .cr-release-packages/
102+
59103 - name : Install cosign
6010461- if : ${{ steps.chart-releaser.outputs.changed_charts }}
105+ if : ${{ steps.chart-releaser.outputs.changed_charts || github.event.inputs.chart != '' }}
62106
63107 - id : github-repo-owner-name
64108 uses : ASzc/change-string-case-action@d0603cd0a7dd490be678164909f65c7737470a7f # v6
@@ -67,129 +111,81 @@ jobs:
67111
68112 - name : Upload charts to OCI registries
69113 id : upload
70- if : ${{ steps.chart-releaser.outputs.changed_charts }}
114+ if : ${{ steps.chart-releaser.outputs.changed_charts || github.event.inputs.chart != '' }}
71115 env :
72116 COSIGN_KEY : ${{ secrets.COSIGN_KEY }}
73117 COSIGN_PASSWORD : ${{ secrets.COSIGN_PASSWORD }}
74118 REGISTRY_USER : ${{ secrets.REGISTRY_USER }}
75119 run : |
76120 set -euo pipefail
77121
78- CHANGED_CHARTS="${{ steps.chart-releaser.outputs.changed_charts }}"
122+ # Determine which charts to release
123+ if [ -n "${{ github.event.inputs.chart }}" ]; then
124+ echo "Manual chart specified: ${{ github.event.inputs.chart }}"
125+ CHANGED_CHARTS="${{ github.event.inputs.chart }}"
126+ else
127+ CHANGED_CHARTS="${{ steps.chart-releaser.outputs.changed_charts }}"
128+ fi
129+
130+
131+ if [ -z "$CHANGED_CHARTS" ]; then
132+ echo "No charts to release."
133+ exit 0
134+ fi
79135
80136 # Retry function for network operations
81137 retry() {
82138 local max_attempts=3
83139 local attempt=1
84140 local delay=5
85-
86141 while [ $attempt -le $max_attempts ]; do
87- if "$@"; then
88- return 0
89- else
90- echo "Attempt $attempt failed. Retrying in ${delay}s..."
91- sleep $delay
92- delay=$((delay * 2))
93- attempt=$((attempt + 1))
94- fi
142+ if "$@"; then return 0; fi
143+ echo "Attempt $attempt failed. Retrying in ${delay}s..."
144+ sleep $delay
145+ delay=$((delay * 2))
146+ attempt=$((attempt + 1))
95147 done
96-
97148 echo "ERROR: All $max_attempts attempts failed"
98149 return 1
99150 }
100151
101- # Login to primary registry with retry
102152 echo "Logging into primary registry..."
103153 retry helm registry login --username $REGISTRY_USER --password ${{ secrets.REGISTRY_PASSWORD }} https://${{ vars.REGISTRY }}
104154
105- # Login to GHCR with retry
106155 echo "Logging into GHCR..."
107156 retry helm registry login --username ${{ github.actor }} --password ${{ secrets.GITHUB_TOKEN }} https://ghcr.io
108157
109158 RELEASED_CHARTS=""
110159 for chart_directory in ${CHANGED_CHARTS//,/ }; do
111160 CHART_NAME=${chart_directory#charts/}
112-
113161 cd $chart_directory
114162
115- # Extract version and appVersion from Chart.yaml
116163 CHART_VERSION=$(yq eval '.version' "Chart.yaml")
117164 APP_VERSION=$(yq eval '.appVersion' "Chart.yaml")
118165
119- # Push to primary registry (Docker Hub) with retry
120166 echo "Pushing Helm chart $CHART_NAME-$CHART_VERSION.tgz to oci://${{ vars.REGISTRY }}/${{ vars.REPOSITORY }}"
121167 if retry helm push ${{ github.workspace }}/.cr-release-packages/${CHART_NAME}-${CHART_VERSION}.tgz oci://${{ vars.REGISTRY }}/${{ vars.REPOSITORY }} 2>&1 | tee ${CHART_NAME}-output.log; then
122-
123- # Extract digest and sign chart
124- # More robust parsing: looks for "Digest: sha256:..." pattern
125168 DIGEST=$(grep -oP 'Digest:\s*\K(sha256:[a-f0-9]+)' ${CHART_NAME}-output.log || echo "")
126-
127- if [ -z "$DIGEST" ]; then
128- echo "ERROR: Failed to extract digest from helm push output"
129- echo "Output was:"
130- cat ${CHART_NAME}-output.log
131- exit 1
132- fi
133-
134- echo "Extracted digest: $DIGEST"
135- echo "Signing chart at ${{ vars.REGISTRY }}/${{ vars.REPOSITORY }}/${CHART_NAME}:${CHART_VERSION}@$DIGEST"
136-
137- if ! cosign sign -y --upload=true --key env://COSIGN_KEY ${{ vars.REGISTRY }}/${{ vars.REPOSITORY }}/${CHART_NAME}:${CHART_VERSION}@$DIGEST; then
138- echo "ERROR: Failed to sign chart"
139- exit 1
140- fi
141-
169+ [ -z "$DIGEST" ] && echo "ERROR: Failed to extract digest" && cat ${CHART_NAME}-output.log && exit 1
170+ cosign sign -y --upload=true --key env://COSIGN_KEY ${{ vars.REGISTRY }}/${{ vars.REPOSITORY }}/${CHART_NAME}:${CHART_VERSION}@$DIGEST
142171 RELEASED_CHARTS="$RELEASED_CHARTS ${CHART_NAME}"
143- echo "Successfully released $CHART_NAME-$CHART_VERSION to primary registry"
144- else
145- echo "ERROR: Failed to push $CHART_NAME-$CHART_VERSION to primary registry"
146- cat ${CHART_NAME}-output.log
147- exit 1
148172 fi
149173
150- # Push to GHCR with retry
151- echo "Pushing Helm chart $CHART_NAME-$CHART_VERSION.tgz to oci://ghcr.io/${{ steps.github-repo-owner-name.outputs.lowercase }}/helm-charts"
174+ echo "Pushing Helm chart $CHART_NAME-$CHART_VERSION.tgz to GHCR..."
152175 if retry helm push ${{ github.workspace }}/.cr-release-packages/${CHART_NAME}-${CHART_VERSION}.tgz oci://ghcr.io/${{ steps.github-repo-owner-name.outputs.lowercase }}/helm-charts 2>&1 | tee ${CHART_NAME}-ghcr-output.log; then
153-
154- # Extract digest and sign GHCR chart
155- # More robust parsing: looks for "Digest: sha256:..." pattern
156176 GHCR_DIGEST=$(grep -oP 'Digest:\s*\K(sha256:[a-f0-9]+)' ${CHART_NAME}-ghcr-output.log || echo "")
157-
158- if [ -z "$GHCR_DIGEST" ]; then
159- echo "ERROR: Failed to extract digest from helm push output"
160- echo "Output was:"
161- cat ${CHART_NAME}-ghcr-output.log
162- exit 1
163- fi
164-
165- echo "Extracted digest: $GHCR_DIGEST"
166- echo "Signing chart at ghcr.io/${{ steps.github-repo-owner-name.outputs.lowercase }}/helm-charts/${CHART_NAME}:${CHART_VERSION}@$GHCR_DIGEST"
167-
168- if ! cosign sign -y --upload=true --key env://COSIGN_KEY ghcr.io/${{ steps.github-repo-owner-name.outputs.lowercase }}/helm-charts/${CHART_NAME}:${CHART_VERSION}@$GHCR_DIGEST; then
169- echo "ERROR: Failed to sign chart"
170- exit 1
171- fi
172-
173- echo "Successfully released $CHART_NAME-$CHART_VERSION to GHCR"
174- else
175- echo "ERROR: Failed to push $CHART_NAME-$CHART_VERSION to GHCR"
176- cat ${CHART_NAME}-ghcr-output.log
177- exit 1
177+ [ -z "$GHCR_DIGEST" ] && echo "ERROR: Failed to extract GHCR digest" && cat ${CHART_NAME}-ghcr-output.log && exit 1
178+ cosign sign -y --upload=true --key env://COSIGN_KEY ghcr.io/${{ steps.github-repo-owner-name.outputs.lowercase }}/helm-charts/${CHART_NAME}:${CHART_VERSION}@$GHCR_DIGEST
178179 fi
179180
180181 cd ${{ github.workspace }}
181182 done
182- echo "released_charts=$RELEASED_CHARTS" >> "$GITHUB_OUTPUT"
183183
184- # Generate job summary
184+ echo "released_charts=$RELEASED_CHARTS" >> "$GITHUB_OUTPUT"
185185 echo "## 📦 Helm Charts Released" >> $GITHUB_STEP_SUMMARY
186- echo "" >> $GITHUB_STEP_SUMMARY
187- echo "Successfully released the following charts:" >> $GITHUB_STEP_SUMMARY
188- echo "" >> $GITHUB_STEP_SUMMARY
189186 for chart in $RELEASED_CHARTS; do
190187 echo "- ✅ **$chart**" >> $GITHUB_STEP_SUMMARY
191188 done
192- echo "" >> $GITHUB_STEP_SUMMARY
193189 echo "### 📍 Registries" >> $GITHUB_STEP_SUMMARY
194190 echo "- Primary: \`${{ vars.REGISTRY }}/${{ vars.REPOSITORY }}\`" >> $GITHUB_STEP_SUMMARY
195191 echo "- GHCR: \`ghcr.io/${{ steps.github-repo-owner-name.outputs.lowercase }}/helm-charts\`" >> $GITHUB_STEP_SUMMARY
0 commit comments