Skip to main content

Github Action deployment

Prerequisites

  • A project created on CloudFlow.
  • A Dockerfile in your GitHub repository to build your app.

Create a CloudFlow API Token

  1. Log in to the CloudFlow console.
  2. In the left sidebar, click API Tokens.
  3. In the Token Description field, enter a description for what this API token will be used for.
  4. Click Add and copy the created API token.

Get your project endpoint URL

  1. In the CloudFlow console, click on the settings icon on the project card.
  2. Copy the Kubernetes API endpoint.

Get a Github Personal Access token

  1. Click Developer settings under your Github Account settings and then Personal access tokens.
  2. Under Tokens (classic) click Generate new token (classic).
  3. Set Expiration to No expiration. While GitHub recommends giving the token an expiry date, that means that you will have to regenerate the token and repeat the step on expiration.
  4. Enter a descriptive name for the token in the Note field and check the read:packages scope.
  5. Click Generate token and copy it.

Add Secrets to GitHub Repo

  1. In the Settings tab of your Github repository click Secrets and variables.
  2. Under Actions, click New repository secret and add the following secrets:
    • Name: CLOUDFLOW_API_TOKEN, Value: (The API token you created in Step 1)
    • Name: CLOUDFLOW_K8S_API_URL, Value: (The Kubernetes API endpoint you copied in Step 2)
    • Name: GITHUB_IMAGE_PULL_TOKEN, Value: (The Github Personal Access token you created in Step 3)

Create the Required Directory Structure and Files

We are going to create the following directory structure with the required files to automate deploying to CloudFlow:

.
├── .github
│ └── workflows
│ └── deploy-to-cloudflow.yaml
├── ci
│ └── deploy.sh
├── k8s
│ └── deploy.yaml
│ └── ingress-upstream.yaml
├── Dockerfile
├── README.md
└── ...

Setup the CI script

  1. In your GitHub repository, create a directory named ci.
  2. Inside the ci directory, create a file named deploy.sh and paste the provided script.
  3. Make sure to set the executable permission for the deploy.sh file by running chmod +x ci/deploy.sh.
#!/bin/bash
test -z "${DEBUG}" || set -o xtrace
set -o errexit

cd "$(dirname "$0")"

cert=/etc/ssl/certs/ca-certificates.crt

main() {
setCluster

# Required when deploying from a private repository.
kubectl create secret docker-registry github-container-registry --docker-server=ghcr.io --docker-username=<github-username> --docker-password=$GITHUB_IMAGE_PULL_TOKEN || true

envsubst '$IMAGE_NAME' < ../k8s/deploy.yaml | kubectl apply -f -
kubectl apply -f ../k8s/ingress-upstream.yaml

kubectl rollout restart deployment cloudflow-project-deployment

}

setCluster() {
# Configure kubectl to talk to CloudFlow

# change the cert path depending on OS.
if [[ "$OSTYPE" == "darwin"* ]]; then
cert=/usr/local/etc/ca-certificates/cert.pem
fi

kubectl config set-cluster cloudflow \
--server=$CLOUDFLOW_K8S_API_URL \
--certificate-authority=$cert

kubectl config set-credentials cloudflow-user --token=$CLOUDFLOW_API_TOKEN

kubectl config set-context my-cloudflow-application --cluster=cloudflow --user=cloudflow-user --namespace=default

kubectl config use-context my-cloudflow-application

kubectl version
}

"$@"

Create the definition for your app

  1. Create a directory named k8s in the root of your repository.
  2. Inside the k8s directory, create a file named deploy.yaml and paste the provided deploy.yaml content. This will contain the definition to deploy your app on CloudFlow.
apiVersion: apps/v1
kind: Deployment
metadata:
name: cloudflow-project-deployment
labels:
app: console-project
spec:
replicas: 1
selector:
matchLabels:
app: console-project
template:
metadata:
labels:
app: console-project
spec:
containers:
- name: console-project
image: ghcr.io/${IMAGE_NAME}:main
imagePullPolicy: Always
imagePullSecrets:
- name: github-container-registry
resources:
requests:
memory: "200Mi"
cpu: "200m"
limits:
memory: "200Mi"
cpu: "200m"
ports:
- containerPort: 80

Create the definition for your ingress

Inside the k8s directory, create a file named ingress-upstream.yaml and paste the provided ingress-upstream.yaml content. This will contain the definition to direct traffic to your app on CloudFlow.

apiVersion: v1
kind: Service
metadata:
labels:
app: ingress-upstream
name: ingress-upstream
spec:
ports:
- name: 80-80
port: 80
protocol: TCP
targetPort: 80
selector:
app: console-project
sessionAffinity: None
type: ClusterIP

Create a GitHub Action Workflow

  1. Create a new file .github/workflows/deploy-to-cloudflow.yml.
  2. Copy and paste the following into the file:
name: Deployed to CloudFlow

on:
push:
branches:
- main

env:
REGISTRY: ghcr.io
REPO: ${{ github.repository }}

jobs:
build-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: downcase REPO
run: |
echo "IMAGE_NAME=${REPO,,}" >>${GITHUB_ENV}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

- name: Build and push Docker image
uses: docker/build-push-action@v3
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

- name: Deploy on CloudFlow
env:
CLOUDFLOW_K8S_API_URL: "${{ secrets.CLOUDFLOW_K8S_API_URL }}"
CLOUDFLOW_API_TOKEN: "${{ secrets.CLOUDFLOW_API_TOKEN }}"
GITHUB_IMAGE_PULL_TOKEN: "${{ secrets.GITHUB_IMAGE_PULL_TOKEN }}"
DEBUG: 1
run: |
./ci/deploy.sh main

Commit and push to your repository.

Now, every time you push to the main branch or manually trigger the workflow, the GitHub Action will build and deploy your app to CloudFlow.