diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index daf913e4..e4d0213d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,9 @@ on: pull_request: branches: [main] +permissions: + contents: read + jobs: validate: name: Build @@ -32,3 +35,42 @@ jobs: - name: Run CI Tasks (Turbo) run: pnpm turbo validate:build + + publish: + name: Publish image + runs-on: ubuntu-latest + needs: validate + if: github.event_name == 'push' + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Generate image tag + id: image + shell: bash + run: | + branch="$(printf '%s' "$GITHUB_REF_NAME" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//; s/-+/-/g')" + if [ -z "$branch" ]; then + branch="unknown" + fi + + short_sha="${GITHUB_SHA::7}" + timestamp="$(date +%s)" + + tag="${branch}-${short_sha}-${timestamp}" + + echo "tag=${tag}" >> "$GITHUB_OUTPUT" + + - name: Login to Harbor + uses: docker/login-action@v4 + with: + registry: ${{ secrets.REGISTRY_URL }} + username: ${{ secrets.REGISTRY_USERNAME }} + password: ${{ secrets.REGISTRY_PASSWORD }} + + - name: Build and push image + uses: docker/build-push-action@v7 + with: + context: . + push: true + tags: ${{ secrets.REGISTRY_URL }}/web/howto:${{ steps.image.outputs.tag }} diff --git a/Dockerfile b/Dockerfile index 6bcb307b..e5baf426 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,6 +17,6 @@ RUN pnpm --filter docs build FROM nginx:alpine AS runtime COPY --from=builder /app/apps/docs/dist /usr/share/nginx/html -COPY nginx.conf /etc/nginx/nginx.conf +COPY deployment/nginx.conf /etc/nginx/nginx.conf -EXPOSE 80 +EXPOSE 8080 diff --git a/deploy/production/deployment.yaml b/deploy/production/deployment.yaml new file mode 100644 index 00000000..880bfeeb --- /dev/null +++ b/deploy/production/deployment.yaml @@ -0,0 +1,35 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: howto + labels: + app.kubernetes.io/name: howto + app.kubernetes.io/part-of: howto +spec: + replicas: 2 + selector: + matchLabels: + app.kubernetes.io/name: howto + template: + metadata: + labels: + app.kubernetes.io/name: howto + app.kubernetes.io/part-of: howto + spec: + imagePullSecrets: + - name: harbor-regcred + containers: + - name: howto + image: registry.timolia.systems/web/howto:main-0000000-1 # {"$imagepolicy": "web-live:howto"} + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 8080 + readinessProbe: + httpGet: + path: / + port: http + livenessProbe: + httpGet: + path: / + port: http diff --git a/deploy/production/httproute.yaml b/deploy/production/httproute.yaml new file mode 100644 index 00000000..1943af53 --- /dev/null +++ b/deploy/production/httproute.yaml @@ -0,0 +1,19 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: howto + labels: + app.kubernetes.io/name: howto + app.kubernetes.io/part-of: howto +spec: + hostnames: + - howto.timolia.de + parentRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: timolia-gateway + namespace: envoy-gateway-system + rules: + - backendRefs: + - name: howto + port: 80 diff --git a/deploy/production/kustomization.yaml b/deploy/production/kustomization.yaml new file mode 100644 index 00000000..f148229a --- /dev/null +++ b/deploy/production/kustomization.yaml @@ -0,0 +1,7 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: web-live +resources: + - deployment.yaml + - service.yaml + - httproute.yaml diff --git a/deploy/production/service.yaml b/deploy/production/service.yaml new file mode 100644 index 00000000..ce03a729 --- /dev/null +++ b/deploy/production/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: howto + labels: + app.kubernetes.io/name: howto + app.kubernetes.io/part-of: howto +spec: + selector: + app.kubernetes.io/name: howto + ports: + - name: http + port: 80 + targetPort: http diff --git a/deployment/nginx.conf b/deployment/nginx.conf new file mode 100644 index 00000000..e0292303 --- /dev/null +++ b/deployment/nginx.conf @@ -0,0 +1,40 @@ +worker_processes auto; + +events { + worker_connections 1024; +} + +http { + server_tokens off; + + server { + listen 8080; + server_name _; + + root /usr/share/nginx/html; + index index.html index.htm; + include /etc/nginx/mime.types; + + gzip on; + gzip_vary on; + gzip_min_length 1000; + gzip_proxied expired no-cache no-store private auth; + gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; + + location /_astro/ { + expires 1y; + add_header Cache-Control "public, immutable"; + try_files $uri =404; + } + + error_page 404 /404.html; + location = /404.html { + root /usr/share/nginx/html; + internal; + } + + location / { + try_files $uri $uri/index.html =404; + } + } +}