Skip to content

Some improvements to preview action #8

Some improvements to preview action

Some improvements to preview action #8

name: Build and Push Docker Image and then deploy it.
on:
push:
branches:
- main
pull_request:
branches:
- main
types:
- labeled
- unlabeled
- closed
- synchronize
release:
types:
- created
workflow_dispatch:
jobs:
build-and-push:
if: github.event.action != 'labeled' && github.event.action != 'unlabeled'
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push Docker Image
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
platforms: linux/amd64,linux/arm64/v8
tags: |
bacherik/killedby:${{ github.event_name == 'push' && 'latest' || github.event_name == 'release' && github.event.release.tag_name || 'pr-' }}${{ github.event.pull_request.number || '' }}
bacherik/killedby:${{ github.sha }}
- name: Logout from DockerHub
run: docker logout
deploy-main:
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs: build-and-push
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Check if running in a pull request
if: ${{ github.event_name == 'pull_request' }}
run: echo "Running in a pull request, aborting workflow." && exit 0
- name: Deploy to Kubernetes
run: |
mkdir -p k8s
cat <<EOF > k8s/deployment.yaml
apiVersion: v1
kind: Namespace
metadata:
name: killedby-latest
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: killedby-latest
namespace: killedby-latest
spec:
replicas: 1
selector:
matchLabels:
app: killedby-latest
template:
metadata:
labels:
app: killedby-latest
spec:
containers:
- name: killedby-latest
image: bacherik/killedby:latest
imagePullPolicy: Always
env:
- name: GITHUB_USERNAME
value: "bacherik"
- name: GITHUB_REPOSITORY
value: "killedby.json"
- name: UPDATE_TOKEN
value: "${{ secrets.UPDATE_TOKEN }}"
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: killedby-latest
namespace: killedby-latest
spec:
selector:
app: killedby-latest
ports:
- protocol: TCP
port: 80
targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: killedby-latest
namespace: killedby-latest
annotations:
cert-manager.io/cluster-issuer: "letsencrypt"
kubernetes.io/ingress.class: traefik
ingress.kubernetes.io/whitelist-source-range: "192.168.0.0/16"
spec:
tls:
- hosts:
- latest.killedby.bacherik.de
secretName: killedby-latest-tls
rules:
- host: latest.killedby.bacherik.de
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: killedby-latest
port:
number: 80
EOF
- name: Deploy to Kubernetes
uses: actions-hub/[email protected]
env:
KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
with:
args: apply -f k8s/
deploy-preview:
needs: build-and-push
if: success() && (github.event.action == 'labeled' && github.event.label.name == 'deploy-preview') || (github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'deploy-preview'))
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Create or Update Resources
run: |
mkdir -p k8s
cat <<EOF > k8s/deployment.yaml
apiVersion: v1
kind: Namespace
metadata:
name: killedbypr${{ github.event.pull_request.number }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: killedby
namespace: killedbypr${{ github.event.pull_request.number }}
spec:
replicas: 1
selector:
matchLabels:
app: killedby
template:
metadata:
labels:
app: killedby
spec:
containers:
- name: killedby
image: bacherik/killedby:${{ github.sha }}
imagePullPolicy: Always
env:
- name: GITHUB_USERNAME
value: "bacherik"
- name: GITHUB_REPOSITORY
value: "killedby.json"
- name: UPDATE_TOKEN
value: "${{ secrets.UPDATE_TOKEN }}"
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: killedby
namespace: killedbypr${{ github.event.pull_request.number }}
spec:
selector:
app: killedby
ports:
- protocol: TCP
port: 80
targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: killedby
namespace: killedbypr${{ github.event.pull_request.number }}
annotations:
cert-manager.io/cluster-issuer: "letsencrypt"
kubernetes.io/ingress.class: traefik
ingress.kubernetes.io/whitelist-source-range: "192.168.0.0/16"
spec:
tls:
- hosts:
- pr-${{ github.event.pull_request.number }}.killedby.bacherik.de
secretName: pr${{ github.event.pull_request.number }}-killedby-tls
rules:
- host: pr-${{ github.event.pull_request.number }}.killedby.bacherik.de
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: killedby
port:
number: 80
EOF
- name: Deploy Kubernetes Resources
uses: actions-hub/[email protected]
env:
KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
with:
args: apply -f k8s/
- name: Delete Existing Comment
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const comments = await github.rest.issues.listComments({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
});
const botComments = comments.data.filter(comment =>
comment.body.includes('Preview is now online') || comment.body.includes('Preview has been deleted')
);
for (const comment of botComments) {
await github.rest.issues.deleteComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: comment.id,
});
}
- name: Write New Comment on PR
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = context.payload.pull_request.number;
const url = `https://pr-${prNumber}.killedby.bacherik.de`;
const updatedAt = new Date().toISOString();
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `🎉 **Preview is now online!**\n\n🔗 [Access Preview Here](${url})\n🕒 Last updated: ${updatedAt}`,
});
cleanup:
if: ${{ github.event.action == 'closed' && contains(github.event.pull_request.labels.*.name, 'deploy-preview') || (github.event.action == 'unlabeled' && github.event.label.name == 'deploy-preview') }}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: Cleanup Kubernetes Resources
uses: actions-hub/[email protected]
env:
KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
with:
args: delete namespace killedbypr${{ github.event.pull_request.number }}
- name: Delete Existing Comment
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const comments = await github.rest.issues.listComments({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
});
const botComments = comments.data.filter(comment =>
comment.body.includes('Preview is now online') || comment.body.includes('Preview has been deleted')
);
for (const comment of botComments) {
await github.rest.issues.deleteComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: comment.id,
});
}
- name: Write comment on PR
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '🚨 **Preview has been deleted.**\n\nThe namespace and resources associated with this pull request have been cleaned up.'
})