diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..07a263f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +node_modules +dist +.astro +public/admin +.env +.env.* +.git +.gitignore +*.md +.DS_Store diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml new file mode 100644 index 0000000..26212a8 --- /dev/null +++ b/.gitea/workflows/build.yaml @@ -0,0 +1,58 @@ +name: Build and Deploy + +on: + push: + branches: + - main + +env: + REGISTRY: git.idealconnected.com + ORG: johannes.gasser + APP: theater-ziefen + GITOPS_REPO: cloud-hosting + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout source + uses: actions/checkout@v4 + + - name: Set image tag + id: tag + run: echo "sha=${GITHUB_SHA::12}" >> "$GITHUB_OUTPUT" + + - name: Log in to Gitea container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ gitea.actor }} + password: ${{ secrets.GITEA_TOKEN }} + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: | + ${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.APP }}:${{ steps.tag.outputs.sha }} + ${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.APP }}:latest + + - name: Update image tag in gitops repo + env: + GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} + SHA: ${{ steps.tag.outputs.sha }} + run: | + git config --global user.email "ci@idealconnected.com" + git config --global user.name "Gitea CI" + git clone \ + "https://${{ gitea.actor }}:${GITEA_TOKEN}@${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.GITOPS_REPO }}.git" \ + /tmp/gitops + cd /tmp/gitops + sed -i \ + "s|image: ${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.APP }}:.*|image: ${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.APP }}:${SHA}|" \ + "apps/${{ env.APP }}/deployment.yaml" + git add "apps/${{ env.APP }}/deployment.yaml" + git diff --cached --quiet && echo "No changes, skipping commit." && exit 0 + git commit -m "ci: update ${{ env.APP }} to ${SHA}" + git push origin main diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..90c65e2 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM node:20-alpine AS builder + +WORKDIR /app + +COPY package.json package-lock.json ./ +RUN npm ci + +COPY . . +RUN npm run build + +FROM nginx:alpine + +RUN rm /etc/nginx/conf.d/default.conf +COPY nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=builder /app/dist /usr/share/nginx/html + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..5a6d0bb --- /dev/null +++ b/nginx.conf @@ -0,0 +1,44 @@ +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + gzip on; + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_types + text/plain + text/css + text/javascript + application/javascript + application/json + application/xml + image/svg+xml; + + # Long-lived cache for Astro's content-hashed assets + location /_astro/ { + expires 1y; + add_header Cache-Control "public, immutable"; + access_log off; + } + + # Long-lived cache for static media + location ~* \.(ico|svg|png|jpg|jpeg|gif|webp|woff|woff2|ttf|eot)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + access_log off; + } + + # Astro outputs pages as directories: /about → about/index.html + location / { + try_files $uri $uri/ $uri/index.html =404; + } + + error_page 404 /404.html; + location = /404.html { + internal; + } +}