Skip to content

Update build-test-deploy.yml #650

Update build-test-deploy.yml

Update build-test-deploy.yml #650

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-22.04
environment: ${{ github.ref_name }}
permissions:
packages: write
contents: read
steps:
- name: checkout
uses: actions/checkout@v4
with:
fetch-depth: 10
submodules: "true"
- 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: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Set up pack
uses: buildpacks/github-actions/[email protected]
- name: Build using heroku/buildpacks:22 CNB
env:
SECRETS_CONTEXT: ${{ toJson(secrets) }}
VARS_CONTEXT: ${{ toJson(vars) }}
run: |
echo -n "$SECRETS_CONTEXT" | jq -r '[to_entries[]|select(.key|startswith("K8S_SECRET_"))]|map("\(.key|sub("K8S_SECRET_"; ""))=\(.value|tostring)")|.[]' > secrets.env
echo -n "$VARS_CONTEXT" | jq -r '[to_entries[]|select(.key|startswith("K8S_SECRET_"))]|map("\(.key|sub("K8S_SECRET_"; ""))=\(.value|tostring)")|.[]' >> secrets.env
echo -n "$SECRETS_CONTEXT" | jq -r '[to_entries[]|select(.key|startswith("LC_K8S_SECRET_"))]|map("\(.key|sub("LC_K8S_SECRET_"; "")|ascii_downcase)=\(.value|tostring)")|.[]' >> secrets.env
echo -n "$VARS_CONTEXT" | jq -r '[to_entries[]|select(.key|startswith("LC_K8S_SECRET_"))]|map("\(.key|sub("LC_K8S_SECRET_"; "")|ascii_downcase)=\(.value|tostring)")|.[]' >> secrets.env
pack build ${{ env.DOCKER_TAG }}/${{ github.ref_name }}/source --env-file secrets.env --builder heroku/builder:22 \
--cache-image ${{ env.DOCKER_TAG }}/${{ github.ref_name }}/source:cache --publish
rm secrets.env
cat > Dockerfile <<EOF
FROM ${{ env.DOCKER_TAG }}/${{ github.ref_name }}/source
ENV PORT=5000
EXPOSE 5000
EOF
- name: Build and push to ghcr.io
uses: docker/build-push-action@v5
with:
context: .
build-args: |
default_port=5000
source_image=${{ env.DOCKER_TAG }}/${{ github.ref_name }}/source
platforms: linux/amd64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
test:
name: Test code from the branch ${{ github.ref_name }}
runs-on: ubuntu-22.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/*:/}
echo "repository: $repository"
echo "tag: $tag"
cat > auto-deploy-app-values.yaml <<EOF
replicaCount: 1
image:
repository: $repository
tag: "latest"
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