Skip to content

Update build-test-deploy.yml #516

Update build-test-deploy.yml

Update build-test-deploy.yml #516

name: Build test and deploy DHCR
env:
DOCKER_TAG: ${{ secrets.DOCKER_TAG }}
on:
push: {}
repository_dispatch:
types: [run]
jobs:
build:
name: Build Docker image from the branch ${{ github.ref_name }}
runs-on: ubuntu-20.04
environment: ${{ github.ref_name }}
steps:
- name: checkout
uses: actions/checkout@v4
- name: Pack Build
uses: dfreilich/[email protected]
with:
args: 'build tmp-cnb-image --builder heroku/builder:22'
- name: Suggest default port 5000 within image
run: |
echo -n "$SECRETS_CONTEXT" | jq -r '[to_entries[]|select(.key|startswith("K8S_SECRET_"))]|map("\(.key|sub("K8S_SECRET_"; ""))=\(.value|tostring|@sh)")|.[]' > secrets.env
cat >> Dockerfile <<EOF
FROM tmp-cnb-image
ENV PORT=5000
EXPOSE 5000
EOF
- name: login to github container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create tags based on git data
id: meta
uses: docker/metadata-action@v5
with:
images: |
${{ env.DOCKER_TAG }}/${{ github.ref_name }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value={{sha}}
- name: Build and push to ghcr.io
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64
push: true
secret-files: |
"secrets_env=./secrets.env"
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
test:
name: Test code from the branch ${{ github.ref_name }}
runs-on: ubuntu-20.04
environment: ${{ github.ref_name }}
steps:
- name: checkout
uses: actions/checkout@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Run tests using heroku buildpack
run: |
cat <<EOF > Dockerfile
FROM gliderlabs/herokuish
COPY . /tmp/app
ENV USER=herokuishuser
EOF
- name: Build
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64
push: false
tags: |
${{ env.DOCKER_TAG }}:${{ github.ref_name }}-${{ github.sha }}-test
- name: Create test services network
run: |
docker network create --internal test-services
- name: Set up a test database container
run: |
# The following service is isolated from the internet
docker run -d --network test-services -p 3306:3306 --name ${{ secrets.TEST_DB_HOST }} -e MARIADB_SKIP_TEST_DB=yes -e ALLOW_EMPTY_PASSWORD=yes -e MARIADB_USER=${{ secrets.TEST_DB_USER }} -e MARIADB_PASSWORD=${{ secrets.TEST_DB_PASS }} -e MARIADB_DATABASE=${{ secrets.TEST_DB_NAME }} bitnami/mariadb:latest
- name: Run tests using herokuish and heroku buildpack (DB credentials in multiple variables)
# This is a bit more elaborate so the container has access to the internet via the host
# and in addition to the test services network which is isolated from the internet
run: |
cid=$(docker create -t -e TEST_DB_HOST=${{ secrets.TEST_DB_HOST }} -e TEST_DB_NAME=${{ secrets.TEST_DB_NAME }} -e DB_USER=${{ secrets.TEST_DB_USER }} -e DB_PASS=${{ secrets.TEST_DB_PASS }} -e MAIL_SMTP_HOST=${{ secrets.TEST_MAIL_SMTP_HOST }} -e MAIL_SMTP_PORT=${{ secrets.TEST_MAIL_SMTP_PORT }} -e MAIL_SMTP_USER=${{ secrets.TEST_MAIL_SMTP_USER }} -e MAIL_SMTP_PASS=${{ secrets.TEST_MAIL_SMTP_PASS }} -e APP_MAIL_DEFAULT_FROM=${{ secrets.K8S_SECRET_APP_MAIL_DEFAULT_FROM }} -e APP_MAIL_DEFAULT_REPLY_TO=${{ secrets.K8S_SECRET_APP_MAIL_DEFAULT_REPLY_TO }} -e APP_MAIL_DEFAULT_CC=${{ secrets.K8S_SECRET_APP_MAIL_DEFAULT_CC }} -e DEBUG_MAIL_TO=${{ secrets.K8S_SECRET_DEBUG_MAIL_TO }} ${{ env.DOCKER_TAG }}:${{ github.ref_name }}-${{ github.sha }}-test /bin/herokuish buildpack test)
docker network connect test-services $cid
docker start -i $cid
deploy:
needs: [build, test]
name: Deploy Docker image from the branch ${{ github.ref_name }}
runs-on: 'ubuntu-latest'
environment: ${{ github.ref_name }}
env:
SECRETS_CONTEXT: ${{ toJson(secrets) }}
steps:
- uses: actions/checkout@v4
name: Checkout
- name: Kubernetes credentials
run: |
mkdir ${HOME}/.kube
echo ${{ secrets.C2_KUBE_CONFIG }} | base64 --decode > ${HOME}/.kube/config
chmod 0600 ${HOME}/.kube/config
KUBE_NAMESPACE="${{ secrets.KUBE_NAMESPACE }}"
if [ "$KUBE_NAMESPACE"x == 'x' ]
then KUBE_NAMESPACE="${{ inputs.APP_NAME }}-${{ github.ref_name }}"
fi
echo "KUBE_NAMESPACE=$KUBE_NAMESPACE" >> $GITHUB_ENV
kubectl config set-context --current --namespace=${{ secrets.KUBE_NAMESPACE }}
kubectl get pod
- name: Create tags based on git data
id: meta
uses: docker/metadata-action@v5
with:
images: |
${{ env.DOCKER_TAG }}/${{ github.ref_name }}
tags: |
type=raw,value={{sha}}
- name: Create auto-deploy-app-values.yaml
run: |
docker_tag="${{ steps.meta.outputs.tags }}"
repository=${docker_tag/:*/}
tag=${docker_tag/*:/}
cat > auto-deploy-app-values.yaml <<EOF
replicaCount: 1
image:
repository: $repository
tag: $tag
pullPolicy: Always
extraLabels:
"ID": "${{ secrets.SERVICE_ID }}"
github:
app: ${{ secrets.APP_NAME }}
envURL: ${{ github.repositoryUrl }}
service:
enabled: true
name: ${{ secrets.APP_NAME }}-${{ github.ref_name }}
url: ${{ secrets.PUBLIC_URL }}
type: ClusterIP
externalPort: 5000
internalPort: 5000
ingress:
enabled: true
path: "/"
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/proxy-connect-timeout: '600'
kubernetes.io/ingress.class: "nginx"
kubernetes.io/proxy-read-timeout: "3600"
EOF
if [ '${{ secrets.APP_ROOT }}x' != '/x' ]
then echo ' nginx.ingress.kubernetes.io/app-root: ${{ secrets.APP_ROOT }}' >> auto-deploy-app-values.yaml
fi
cat >> auto-deploy-app-values.yaml <<EOF
livenessProbe:
path: "${{ secrets.APP_ROOT }}"
initialDelaySeconds: 25
timeoutSeconds: 30
scheme: "HTTP"
probeType: "httpGet"
readinessProbe:
path: "${{ secrets.APP_ROOT }}"
initialDelaySeconds: 15
timeoutSeconds: 30
scheme: "HTTP"
probeType: "httpGet"
EOF
- name: 'Save config for debugging'
uses: actions/upload-artifact@v4
with:
name: auto-deploy-yamls
path: |
auto-deploy-app-values.yaml
retention-days: 5
- name: Set environment variables
env:
SECRETS_CONTEXT: ${{ toJson(secrets) }}
run: |
cat > secrets.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:
name: ${{ secrets.APP_NAME }}-${{ github.ref_name }}
type: Opaque
data:
EOF
k8s_secrets=$(echo -n "$SECRETS_CONTEXT" | jq -r '[to_entries[]|select(.key|startswith("K8S_SECRET_"))]|map(" \(.key|sub("K8S_SECRET_"; "")): \(.value|tostring|@base64)")|.[]')
if [ "$k8s_secrets"x == 'x' ]
then echo ' {}' >> secrets.yaml
else echo "$k8s_secrets" >> secrets.yaml
fi
kubectl replace -f secrets.yaml -n "${{ secrets.KUBE_NAMESPACE }}" --force
rm secrets.yaml
- name: Deploy using helm and the local helm chart
env:
SECRETS_CONTEXT: ${{ toJson(secrets) }}
run: |
helm upgrade "${{ secrets.APP_NAME }}-${{ github.ref_name }}" \
--values auto-deploy-app-values.yaml --install --atomic --wait \
--set application.secretName="${{ secrets.APP_NAME }}-${{ github.ref_name }}" ${{ secrets.HELM_UPGRADE_EXTRA_ARGS }} \
.github/auto-deploy-app