Skip to content

Commit f5311f6

Browse files
committed
Added gha pipeline to publish helm chart
1 parent 0d44bc7 commit f5311f6

15 files changed

Lines changed: 722 additions & 0 deletions

File tree

.github/workflows/ci-cd.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,64 @@ jobs:
130130
cache-to: type=gha,scope=build-nginx,mode=max
131131
build-args: |
132132
VERSION=${{ github.sha }}
133+
134+
package-helm-chart:
135+
name: Package Helm Chart
136+
runs-on: ubuntu-latest
137+
needs: [build-and-push-fpm, build-and-push-nginx]
138+
permissions:
139+
contents: read
140+
packages: write
141+
142+
steps:
143+
- name: Checkout code
144+
uses: actions/checkout@v4
145+
146+
- name: Set environment variables
147+
id: set-variables
148+
run: |
149+
echo "REPOSITORY=ghcr.io/$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT"
150+
echo "VERSION=$(yq -r .version ./kubernetes/charts/sosticket/Chart.yaml)" >> "$GITHUB_OUTPUT"
151+
152+
- name: Env variable output
153+
id: test-variables
154+
run: |
155+
echo ${{ steps.set-variables.outputs.REPOSITORY }}
156+
echo ${{ steps.set-variables.outputs.VERSION }}
157+
158+
- name: Login to GitHub Container Registry
159+
uses: docker/login-action@v3
160+
with:
161+
registry: ghcr.io
162+
username: ${{ github.actor }}
163+
password: ${{ github.token }}
164+
165+
- name: Package and push helm chart
166+
run: |
167+
helm package ./kubernetes/charts/osticket --version ${{ steps.set-variables.outputs.VERSION }}
168+
helm push ./sample-app-chart-${{ steps.set-variables.outputs.VERSION }}.tgz oci://${{ steps.set-variables.outputs.REPOSITORY }}/charts
169+
170+
publish-helm-chart:
171+
name: Publish Helm Chart
172+
runs-on: ubuntu-latest
173+
needs: [package-helm-chart]
174+
permissions:
175+
id-token: write
176+
packages: write
177+
contents: write
178+
actions: read
179+
deployments: read
180+
pull-requests: read
181+
182+
steps:
183+
- name: Checkout code
184+
uses: actions/checkout@v4
185+
186+
- name: Publish Helm chart to GitHub Pages
187+
uses: stefanprodan/helm-gh-pages@0ad2bb377311d61ac04ad9eb6f252fb68e207260 # v1.7.0
188+
with:
189+
token: ${{ secrets.GITHUB_TOKEN }}
190+
# linting: off
191+
repository: helm-charts
192+
branch: gh-pages
193+
target_dir: charts
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Patterns to ignore when building packages.
2+
# This supports shell glob matching, relative path matching, and
3+
# negation (prefixed with !). Only one pattern per line.
4+
.DS_Store
5+
# Common VCS dirs
6+
.git/
7+
.gitignore
8+
.bzr/
9+
.bzrignore
10+
.hg/
11+
.hgignore
12+
.svn/
13+
# Common backup files
14+
*.swp
15+
*.bak
16+
*.tmp
17+
*.orig
18+
*~
19+
# Various IDEs
20+
.project
21+
.idea/
22+
*.tmproj
23+
.vscode/
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
dependencies:
2+
- name: mariadb
3+
repository: https://charts.bitnami.com/bitnami
4+
version: 20.5.3
5+
digest: sha256:8fda5bf8e7f510359ea3ecc7f11278f060144901e83cb7e1ae7ae8cda55112b4
6+
generated: "2025-06-02T22:12:01.991995+01:00"
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
apiVersion: v2
2+
name: osticket
3+
description: A Helm chart for Kubernetes
4+
maintainers:
5+
- name: Devops Consultants
6+
email: rob.coward@devops-consultants.co.uk
7+
# A chart can be either an 'application' or a 'library' chart.
8+
#
9+
# Application charts are a collection of templates that can be packaged into versioned archives
10+
# to be deployed.
11+
#
12+
# Library charts provide useful utilities or functions for the chart developer. They're included as
13+
# a dependency of application charts to inject those utilities and functions into the rendering
14+
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
15+
type: application
16+
17+
# This is the chart version. This version number should be incremented each time you make changes
18+
# to the chart and its templates, including the app version.
19+
# Versions are expected to follow Semantic Versioning (https://semver.org/)
20+
version: 0.1.5
21+
22+
# This is the version number of the application being deployed. This version number should be
23+
# incremented each time you make changes to the application. Versions are not expected to
24+
# follow Semantic Versioning. They should reflect the version the application is using.
25+
# It is recommended to use it with quotes.
26+
appVersion: 1.18.2
27+
28+
# osTicket depends on the following charts:
29+
dependencies:
30+
- name: mariadb
31+
version: 20.5.3
32+
repository: https://charts.bitnami.com/bitnami
33+
condition: mariadb.internal
72.6 KB
Binary file not shown.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
1. Get the application URL by running these commands:
2+
{{- if .Values.ingress.enabled }}
3+
{{- range $host := .Values.ingress.hosts }}
4+
{{- range .paths }}
5+
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
6+
{{- end }}
7+
{{- end }}
8+
{{- else if contains "NodePort" .Values.service.type }}
9+
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "osticket.fullname" . }})
10+
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
11+
echo http://$NODE_IP:$NODE_PORT
12+
{{- else if contains "LoadBalancer" .Values.service.type }}
13+
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
14+
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "osticket.fullname" . }}'
15+
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "osticket.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
16+
echo http://$SERVICE_IP:{{ .Values.service.port }}
17+
{{- else if contains "ClusterIP" .Values.service.type }}
18+
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "osticket.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
19+
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
20+
echo "Visit http://127.0.0.1:8080 to use your application"
21+
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
22+
{{- end }}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{{/*
2+
Expand the name of the chart.
3+
*/}}
4+
{{- define "osticket.name" -}}
5+
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
6+
{{- end }}
7+
8+
{{/*
9+
Create a default fully qualified app name.
10+
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
11+
If release name contains chart name it will be used as a full name.
12+
*/}}
13+
{{- define "osticket.fullname" -}}
14+
{{- if .Values.fullnameOverride }}
15+
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
16+
{{- else }}
17+
{{- $name := default .Chart.Name .Values.nameOverride }}
18+
{{- if contains $name .Release.Name }}
19+
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
20+
{{- else }}
21+
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
22+
{{- end }}
23+
{{- end }}
24+
{{- end }}
25+
26+
{{/*
27+
Create chart name and version as used by the chart label.
28+
*/}}
29+
{{- define "osticket.chart" -}}
30+
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
31+
{{- end }}
32+
33+
{{/*
34+
Common labels
35+
*/}}
36+
{{- define "osticket.labels" -}}
37+
helm.sh/chart: {{ include "osticket.chart" . }}
38+
{{ include "osticket.selectorLabels" . }}
39+
{{- if .Chart.AppVersion }}
40+
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
41+
{{- end }}
42+
app.kubernetes.io/managed-by: {{ .Release.Service }}
43+
{{- end }}
44+
45+
{{/*
46+
Selector labels
47+
*/}}
48+
{{- define "osticket.selectorLabels" -}}
49+
app.kubernetes.io/name: {{ include "osticket.name" . }}
50+
app.kubernetes.io/instance: {{ .Release.Name }}
51+
{{- end }}
52+
53+
{{/*
54+
Create the name of the service account to use
55+
*/}}
56+
{{- define "osticket.serviceAccountName" -}}
57+
{{- if .Values.serviceAccount.create }}
58+
{{- default (include "osticket.fullname" .) .Values.serviceAccount.name }}
59+
{{- else }}
60+
{{- default "default" .Values.serviceAccount.name }}
61+
{{- end }}
62+
{{- end }}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: {{ include "osticket.fullname" . }}
5+
labels:
6+
{{- include "osticket.labels" . | nindent 4 }}
7+
spec:
8+
{{- if not .Values.autoscaling.enabled }}
9+
replicas: {{ .Values.replicaCount }}
10+
{{- end }}
11+
selector:
12+
matchLabels:
13+
{{- include "osticket.selectorLabels" . | nindent 6 }}
14+
template:
15+
metadata:
16+
{{- with .Values.podAnnotations }}
17+
annotations:
18+
{{- toYaml . | nindent 8 }}
19+
{{- end }}
20+
labels:
21+
{{- include "osticket.labels" . | nindent 8 }}
22+
{{- with .Values.podLabels }}
23+
{{- toYaml . | nindent 8 }}
24+
{{- end }}
25+
spec:
26+
{{- with .Values.imagePullSecrets }}
27+
imagePullSecrets:
28+
{{- toYaml . | nindent 8 }}
29+
{{- end }}
30+
serviceAccountName: {{ include "osticket.serviceAccountName" . }}
31+
securityContext:
32+
{{- toYaml .Values.podSecurityContext | nindent 8 }}
33+
initContainers:
34+
- name: init-osticket
35+
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
36+
imagePullPolicy: {{ .Values.image.pullPolicy }}
37+
command: ["/bin/sh", "-c"]
38+
args:
39+
- |
40+
if [ ! -f /data/var/www/html/include/ost-config.php ]; then
41+
echo "Initializing osTicket configuration...";
42+
php /usr/local/bin/install.php;
43+
chmod 644 /var/www/html/include/ost-config.php;
44+
cp -R /var/www/html/* /data/var/www/html/;
45+
fi
46+
env:
47+
- name: MYSQL_HOST
48+
value: "{{ include "osticket.name" . }}-mariadb"
49+
- name: MYSQL_ROOT_PASSWORD
50+
valueFrom:
51+
secretKeyRef:
52+
name: {{ include "osticket.fullname" . }}-mariadb
53+
key: mariadb-root-password
54+
- name: MQSQL_DATABASE
55+
value: {{ .Values.mariadb.auth.database }}
56+
- name: MYSQL_USER
57+
value: {{ .Values.mariadb.auth.username }}
58+
- name: MYSQL_PASSWORD
59+
valueFrom:
60+
secretKeyRef:
61+
name: {{ include "osticket.fullname" . }}-mariadb
62+
key: mariadb-password
63+
volumeMounts:
64+
- name: osticket-volume
65+
mountPath: /data/var/www/html
66+
67+
containers:
68+
- name: nginx
69+
image: "{{ .Values.nginx.image.repository }}:{{ .Values.nginx.image.tag | default .Chart.AppVersion }}"
70+
imagePullPolicy: {{ .Values.nginx.image.pullPolicy }}
71+
ports:
72+
- name: http
73+
containerPort: {{ .Values.service.port }}
74+
protocol: TCP
75+
env:
76+
- name: FPM_PORT
77+
value: {{ .Values.fpmPort | quote }}
78+
livenessProbe:
79+
{{- toYaml .Values.nginx.livenessProbe | nindent 12 }}
80+
readinessProbe:
81+
{{- toYaml .Values.nginx.readinessProbe | nindent 12 }}
82+
resources:
83+
{{- toYaml .Values.nginx.resources | nindent 12 }}
84+
{{- with .Values.nginx.volumeMounts }}
85+
volumeMounts:
86+
{{- toYaml . | nindent 12 }}
87+
{{- end }}
88+
89+
- name: {{ .Chart.Name }}
90+
securityContext:
91+
{{- toYaml .Values.securityContext | nindent 12 }}
92+
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
93+
imagePullPolicy: {{ .Values.image.pullPolicy }}
94+
ports:
95+
- name: php-fpm
96+
containerPort: {{ .Values.fpmPort }}
97+
protocol: TCP
98+
env:
99+
- name: MYSQL_HOST
100+
value: "{{ include "osticket.name" . }}-mariadb"
101+
- name: MYSQL_ROOT_PASSWORD
102+
valueFrom:
103+
secretKeyRef:
104+
name: {{ include "osticket.fullname" . }}-mariadb
105+
key: mariadb-root-password
106+
- name: MQSQL_DATABASE
107+
value: {{ .Values.mariadb.auth.database }}
108+
- name: MYSQL_USER
109+
value: {{ .Values.mariadb.auth.username }}
110+
- name: MYSQL_PASSWORD
111+
valueFrom:
112+
secretKeyRef:
113+
name: {{ include "osticket.fullname" . }}-mariadb
114+
key: mariadb-password
115+
livenessProbe:
116+
{{- toYaml .Values.livenessProbe | nindent 12 }}
117+
readinessProbe:
118+
{{- toYaml .Values.readinessProbe | nindent 12 }}
119+
resources:
120+
{{- toYaml .Values.resources | nindent 12 }}
121+
{{- with .Values.volumeMounts }}
122+
volumeMounts:
123+
{{- toYaml . | nindent 12 }}
124+
{{- end }}
125+
volumes:
126+
- name: nginx-config
127+
configMap:
128+
name: {{ include "osticket.fullname" . }}-nginx-config
129+
{{- with .Values.volumes }}
130+
{{- toYaml . | nindent 8 }}
131+
{{- end }}
132+
{{- with .Values.nodeSelector }}
133+
nodeSelector:
134+
{{- toYaml . | nindent 8 }}
135+
{{- end }}
136+
{{- with .Values.affinity }}
137+
affinity:
138+
{{- toYaml . | nindent 8 }}
139+
{{- end }}
140+
{{- with .Values.tolerations }}
141+
tolerations:
142+
{{- toYaml . | nindent 8 }}
143+
{{- end }}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{{- if .Values.autoscaling.enabled }}
2+
apiVersion: autoscaling/v2
3+
kind: HorizontalPodAutoscaler
4+
metadata:
5+
name: {{ include "osticket.fullname" . }}
6+
labels:
7+
{{- include "osticket.labels" . | nindent 4 }}
8+
spec:
9+
scaleTargetRef:
10+
apiVersion: apps/v1
11+
kind: Deployment
12+
name: {{ include "osticket.fullname" . }}
13+
minReplicas: {{ .Values.autoscaling.minReplicas }}
14+
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
15+
metrics:
16+
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
17+
- type: Resource
18+
resource:
19+
name: cpu
20+
target:
21+
type: Utilization
22+
averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
23+
{{- end }}
24+
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
25+
- type: Resource
26+
resource:
27+
name: memory
28+
target:
29+
type: Utilization
30+
averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
31+
{{- end }}
32+
{{- end }}

0 commit comments

Comments
 (0)