|
| 1 | +name: Deploy main to Cloudzilla |
| 2 | +on: |
| 3 | + push: |
| 4 | + branches: [main] |
| 5 | + workflow_dispatch: |
| 6 | + |
| 7 | +env: |
| 8 | + IMAGE_PREFIX: registry.cloudzilla.ai/prod-project-79535aa805/main/ |
| 9 | + |
| 10 | +jobs: |
| 11 | + cz-build-push: |
| 12 | + runs-on: ubuntu-latest |
| 13 | + permissions: |
| 14 | + contents: read |
| 15 | + packages: write |
| 16 | + |
| 17 | + steps: |
| 18 | + - name: Checkout |
| 19 | + uses: actions/checkout@v3 |
| 20 | + |
| 21 | + - name: Log in to the Container registry |
| 22 | + uses: docker/login-action@v3 |
| 23 | + with: |
| 24 | + registry: https://registry.cloudzilla.ai/ |
| 25 | + username: 'robot$prod-project-79535aa805+imageuser' |
| 26 | + password: '${{ secrets.CZ_BRANCH_MAIN_DOCKER_PASSWORD }}' |
| 27 | + |
| 28 | + - name: downcase REPO |
| 29 | + run: | |
| 30 | + image="${GITHUB_REPOSITORY#*/}" |
| 31 | + echo "IMAGE_NAME=${image,,}" >>${GITHUB_ENV} |
| 32 | +
|
| 33 | + - name: Extract metadata (tags, labels) for Docker |
| 34 | + id: meta |
| 35 | + uses: docker/metadata-action@v5 |
| 36 | + with: |
| 37 | + images: ${{ env.IMAGE_PREFIX }}${{ env.IMAGE_NAME }} |
| 38 | + |
| 39 | + - name: Validate existing .env file |
| 40 | + run: | |
| 41 | + # Path to your .env file |
| 42 | + ENV_FILE=".env" |
| 43 | + # Check if the .env file exists |
| 44 | + if [ ! -f "$ENV_FILE" ]; then |
| 45 | + # If the .env file doesn't exist, exit the script |
| 46 | + exit 0 |
| 47 | + fi |
| 48 | +
|
| 49 | + # Read the .env file line by line |
| 50 | + while IFS= read -r line || [ -n "$line" ]; do |
| 51 | + # Remove leading and trailing whitespace |
| 52 | + line="$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')" |
| 53 | +
|
| 54 | + # Skip empty lines |
| 55 | + if [ -z "$line" ]; then |
| 56 | + continue |
| 57 | + fi |
| 58 | +
|
| 59 | + # Skip comment lines starting with # |
| 60 | + if [[ "$line" == \#* ]]; then |
| 61 | + continue |
| 62 | + fi |
| 63 | +
|
| 64 | + # Check if the line matches KEY=VALUE format |
| 65 | + if ! [[ "$line" =~ ^[A-Za-z_][A-Za-z0-9_]*=.*$ ]]; then |
| 66 | + echo "Your existing .env file is not valid. Environment variable names (keys) must consist solely of letters, digits, and the underscore ( _ ) and must not begin with a digit according to the .env file specification" |
| 67 | + exit 1 |
| 68 | + fi |
| 69 | + done < "$ENV_FILE" |
| 70 | +
|
| 71 | + - name: Put down .env file |
| 72 | + run: | |
| 73 | + echo "writing .env file..." |
| 74 | + echo "# This file is generated or updated by the cloudzilla deploy workflow" >> .env |
| 75 | + # get the appropriate branch scoped env vars and stript the scoping prefix |
| 76 | + # remove duplicates keeping the items at the bottom of the file |
| 77 | + tac .env | awk -F'=' '!seen[$1]++' | tac > .env.tmp2 && mv .env.tmp2 .env |
| 78 | +
|
| 79 | + - name: Build and push Docker image |
| 80 | + uses: docker/build-push-action@v5 |
| 81 | + with: |
| 82 | + context: . |
| 83 | + push: true |
| 84 | + file: .github/workflows/cloudzilla/main/Dockerfile |
| 85 | + tags: ${{ steps.meta.outputs.tags }} |
| 86 | + labels: ${{ steps.meta.outputs.labels }} |
| 87 | + - name: Deploy on Section |
| 88 | + env: |
| 89 | + SECTION_K8S_API_URL: '${{ secrets.CZ_BRANCH_MAIN_SECTION_K8S_API_URL }}' |
| 90 | + SECTION_API_TOKEN: '${{ secrets.CZ_BRANCH_MAIN_SECTION_API_TOKEN }}' |
| 91 | + DOCKER_SERVER: 'registry.cloudzilla.ai' |
| 92 | + DOCKER_USERNAME: 'robot$prod-project-79535aa805+imageuser' |
| 93 | + DOCKER_PASSWORD: '${{ secrets.CZ_BRANCH_MAIN_DOCKER_PASSWORD }}' |
| 94 | + FULL_IMAGE_WITH_TAG: '${{ env.DOCKER_METADATA_OUTPUT_TAGS }}' |
| 95 | + POD_NAME: '${{ env.IMAGE_NAME }}' |
| 96 | + DEBUG: 1 |
| 97 | + run: | |
| 98 | + #!/bin/bash |
| 99 | + test -z "${DEBUG}" || set -o xtrace |
| 100 | + set +e # revert the default `set -e` which github actions enable automatically |
| 101 | + cd "$(dirname "$0")" |
| 102 | +
|
| 103 | + cert=/etc/ssl/certs/ca-certificates.crt |
| 104 | +
|
| 105 | + # Reusable backoffretry function |
| 106 | + backoffretry() { |
| 107 | + local max_retries=$1 # Maximum number of retries |
| 108 | + local delay=$2 # Initial delay in seconds |
| 109 | + shift 2 |
| 110 | + local command="$@" # Command to execute (e.g., main function) |
| 111 | + local attempt=1 # Current attempt counter |
| 112 | +
|
| 113 | + while [ $attempt -le $max_retries ]; do |
| 114 | + echo "Attempt $attempt of $max_retries" |
| 115 | +
|
| 116 | + # Execute the command |
| 117 | + $command |
| 118 | + local exit_code=$? |
| 119 | +
|
| 120 | + if [ $exit_code -eq 0 ]; then |
| 121 | + echo "Success on attempt $attempt" |
| 122 | + return 0 |
| 123 | + else |
| 124 | + echo "Failure on attempt $attempt with exit code $exit_code" |
| 125 | + fi |
| 126 | +
|
| 127 | + if [ $attempt -lt $max_retries ]; then |
| 128 | + echo "Waiting for $delay seconds before retry..." |
| 129 | + sleep $delay |
| 130 | + delay=$((delay * 2)) # Exponential backoff |
| 131 | + attempt=$((attempt + 1)) |
| 132 | + else |
| 133 | + echo "Exceeded maximum retries. Exiting with failure." |
| 134 | + return $exit_code |
| 135 | + fi |
| 136 | + done |
| 137 | + } |
| 138 | +
|
| 139 | + main() { |
| 140 | + setCluster || return 1 |
| 141 | +
|
| 142 | + kubectl create secret generic console-project-env-secret --from-env-file=${GITHUB_WORKSPACE}/.env --dry-run=client -o yaml | kubectl apply -f - || return 1 |
| 143 | + kubectl create secret docker-registry regcred --docker-server="${DOCKER_SERVER}" --docker-username="${DOCKER_USERNAME}" --docker-password="${DOCKER_PASSWORD}" --dry-run=client -o yaml | kubectl apply -f - || return 1 |
| 144 | + kubectl apply -f ${GITHUB_WORKSPACE}/.github/workflows/cloudzilla/main/k8s/ingress-upstream.yaml || return 1 |
| 145 | + envsubst '$FULL_IMAGE_WITH_TAG $POD_NAME' < ${GITHUB_WORKSPACE}/.github/workflows/cloudzilla/main/k8s/deploy.yaml | kubectl apply -f - || return 1 |
| 146 | + kubectl rollout restart deployment "section-project-deployment" || return 1 |
| 147 | + |
| 148 | + } |
| 149 | +
|
| 150 | + setCluster() { |
| 151 | + # Configure kubectl to talk to Section |
| 152 | + |
| 153 | + # change the cert path depending on OS. |
| 154 | + if [[ "$OSTYPE" == "darwin"* ]]; then |
| 155 | + cert=/usr/local/etc/ca-certificates/cert.pem |
| 156 | + fi |
| 157 | +
|
| 158 | + kubectl config set-cluster section \ |
| 159 | + --server=$SECTION_K8S_API_URL \ |
| 160 | + --certificate-authority=$cert || return 1 |
| 161 | +
|
| 162 | + kubectl config set-credentials section-user --token=$SECTION_API_TOKEN || return 1 |
| 163 | +
|
| 164 | + kubectl config set-context my-section-application --cluster=section --user=section-user --namespace=default || return 1 |
| 165 | +
|
| 166 | + kubectl config use-context my-section-application || return 1 |
| 167 | +
|
| 168 | + kubectl version || return 1 |
| 169 | + } |
| 170 | +
|
| 171 | + # Parameters for backoffretry |
| 172 | + max_retries=4 # Maximum number of retries |
| 173 | + initial_delay=10 # Initial delay before retrying in seconds |
| 174 | +
|
| 175 | + # Call backoffretry with the main function |
| 176 | + backoffretry $max_retries $initial_delay main |
| 177 | + exit_code=$? |
| 178 | + exit $exit_code |
0 commit comments