diff --git a/.forgejo/workflows/README.md b/.forgejo/workflows/README.md new file mode 100644 index 0000000..1274c36 --- /dev/null +++ b/.forgejo/workflows/README.md @@ -0,0 +1,66 @@ +# Forgejo Actions for NextJS Slack Clone + +This directory contains Forgejo action workflow configurations to build, push, and deploy our NextJS Slack Clone application using a secure service account approach. + +## Workflows + +### build-and-deploy.yaml + +This workflow handles: +1. Building the Docker image +2. Pushing the image to the private registry (registrar.mattiaswiberg.com) +3. Deploying the application using Helm to the Kubernetes cluster with service account authentication + +## Required Secrets + +The following secrets need to be configured in your Forgejo repository settings: + +1. `REGISTRY_USERNAME`: Username for the private Docker registry +2. `REGISTRY_PASSWORD`: Password for the private Docker registry +3. `K8S_SERVER_URL`: The Kubernetes API server URL (e.g., https://kubernetes.default.svc or your cluster endpoint) +4. `K8S_CA_CERT`: Base64-encoded certificate authority data for your Kubernetes cluster +5. `K8S_SA_TOKEN`: The service account token with permissions to deploy your application +6. `NEXT_PUBLIC_SUPABASE_URL`: Supabase URL for your project +7. `NEXT_PUBLIC_SUPABASE_ANON_KEY`: Supabase anonymous key for your project + +## Setting Up Service Account Authentication + +For secure Kubernetes authentication, we use a dedicated service account rather than a full kubeconfig. This follows security best practices by providing only the necessary permissions for CI/CD deployments. + +To set up the required secrets: + +1. Deploy the application once manually to create the service account and role +2. Get the service account token and cluster details: + +```bash +# Get the service account token +SECRET_NAME=$(kubectl get serviceaccount nextjs-slack-clone -n default -o jsonpath='{.secrets[0].name}') +TOKEN=$(kubectl get secret $SECRET_NAME -n default -o jsonpath='{.data.token}' | base64 --decode) +echo $TOKEN # This is your K8S_SA_TOKEN + +# Get the cluster CA certificate +CA_CERT=$(kubectl config view --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}') +echo $CA_CERT # This is your K8S_CA_CERT + +# Get the server URL +SERVER_URL=$(kubectl config view --raw -o jsonpath='{.clusters[0].cluster.server}') +echo $SERVER_URL # This is your K8S_SERVER_URL +``` + +3. Go to your repository settings +4. Navigate to "Actions" and then "Secrets" +5. Add each of the required secrets listed above + +## Manual Trigger + +You can also manually trigger the workflow using the "Actions" tab in your repository and selecting the "build-and-deploy" workflow. + +## Monitoring Deployments + +After deployment, you can check the status of your application using: + +```bash +kubectl get pods -l app=nextjs-slack-clone +``` + +Or visit the application at https://chat.mattiaswiberg.com diff --git a/.forgejo/workflows/build-and-deploy.yaml b/.forgejo/workflows/build-and-deploy.yaml new file mode 100644 index 0000000..9ebf00b --- /dev/null +++ b/.forgejo/workflows/build-and-deploy.yaml @@ -0,0 +1,125 @@ +on: + push: + branches: + - main + pull_request: + branches: + - main + # Allow manual trigger + workflow_dispatch: + +env: + REGISTRY: registrar.mattiaswiberg.com + IMAGE_NAME: nextjs-slack-clone + HELM_CHART_PATH: ./helm/nextjs-slack-clone + NAMESPACE: default # Change to your application's namespace + +jobs: + build-and-push: + runs-on: docker + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Docker Buildx + run: | + # Set up buildx for multi-platform builds + docker buildx create --use + + - name: Login to Container Registry + run: | + echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u ${{ secrets.REGISTRY_USERNAME }} --password-stdin + + # Generate a version tag based on commit hash + - name: Generate version tag + id: generate_tag + run: | + COMMIT_HASH=$(echo ${GITHUB_SHA} | cut -c1-7) + VERSION_TAG="${COMMIT_HASH}" + echo "VERSION_TAG=$VERSION_TAG" >> $GITHUB_OUTPUT + # Also set latest tag for convenience + echo "LATEST_TAG=latest" >> $GITHUB_OUTPUT + + # Build and push Docker image + - name: Build and push + run: | + # Build the image + docker build \ + --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.generate_tag.outputs.VERSION_TAG }} \ + --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.generate_tag.outputs.LATEST_TAG }} \ + --build-arg NEXT_PUBLIC_SUPABASE_URL=${{ secrets.NEXT_PUBLIC_SUPABASE_URL }} \ + --build-arg NEXT_PUBLIC_SUPABASE_ANON_KEY=${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }} \ + . + + # Push the image with version tag and latest tag + docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.generate_tag.outputs.VERSION_TAG }} + docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.generate_tag.outputs.LATEST_TAG }} + + deploy: + needs: build-and-push + runs-on: docker + steps: + - name: Checkout code + uses: actions/checkout@v3 + + # Generate the same version tag as build-and-push job + - name: Generate version tag + id: generate_tag + run: | + COMMIT_HASH=$(echo ${GITHUB_SHA} | cut -c1-7) + VERSION_TAG="${COMMIT_HASH}" + echo "VERSION_TAG=$VERSION_TAG" >> $GITHUB_OUTPUT + + - name: Set up kubectl + run: | + # Install kubectl + curl -LO "https://dl.k8s.io/release/stable.txt" + KUBE_VERSION=$(cat stable.txt) + curl -LO "https://dl.k8s.io/release/$KUBE_VERSION/bin/linux/amd64/kubectl" + chmod +x kubectl + mv kubectl /usr/local/bin/ + + - name: Set up Helm + run: | + # Install Helm + curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 + chmod +x get_helm.sh + ./get_helm.sh + + # Create kubeconfig using service account token + - name: Configure kubeconfig from service account + run: | + # Create kubeconfig using service account token + mkdir -p $HOME/.kube + cat > $HOME/.kube/config <