CD & Terraform #123
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# CD pipeline with timeout based cancellation logic to deploy the code on a brand new Scaleway instance | |
name: CD pipeline | |
on: | |
workflow_dispatch: # manual trigger | |
push: | |
branches: ["main"] | |
pull_request: | |
branches: ["main"] | |
jobs: | |
check-condition: | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout repository | |
uses: actions/[email protected] | |
- name: Run condition check | |
uses: ./.github/actions/deployment | |
with: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
approval-timeout: | |
runs-on: ubuntu-latest | |
needs: check-condition | |
if: ${{ needs.check-condition.outputs.RUN_DEPLOYMENT }} == 'true' | |
steps: | |
- name: Wait for approval or timeout | |
run: | | |
ENVIRONMENT_NAME="production" | |
TIMEOUT_MINUTES=15 | |
echo "Waiting $TIMEOUT_MINUTES minutes for approval ..." | |
# iterative checks every minute | |
for ((i=1; i<=$TIMEOUT_MINUTES; i++)); do | |
if [[ $i -gt 1 ]]; then | |
MINUTE_STRING="minutes" | |
else | |
MINUTE_STRING="minute" | |
fi | |
sleep 60 | |
echo "Checking status after $i $MINUTE_STRING ..." | |
DEPLOYMENT_RESPONSE=$(curl -s \ | |
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ | |
-H "Accept: application/vnd.github.v3+json" \ | |
"https://api.github.com/repos/${{ github.repository }}/deployments?environment=$ENVIRONMENT_NAME&per_page=1") | |
DEPLOYMENT_ID=$(echo "$DEPLOYMENT_RESPONSE" | jq -r '.[0].id') | |
STATUS_RESPONSE=$(curl -s \ | |
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ | |
-H "Accept: application/vnd.github.v3+json" \ | |
"https://api.github.com/repos/${{ github.repository }}/deployments/$DEPLOYMENT_ID/statuses") | |
STATUS=$(echo "$STATUS_RESPONSE" | jq -r '.[0].state') | |
if [[ ($STATUS == "error" || "$STATUS" == "waiting") && $i -lt $TIMEOUT_MINUTES ]]; then | |
echo "Approval not received yet - keep waiting for it" | |
else | |
break | |
fi | |
done | |
# tags: error, failure, inactive, in_progress, queued, pending, success | |
echo "Current deployment status is '$STATUS'" | |
if [[ $STATUS != "error" && "$STATUS" != "waiting" ]]; then | |
echo "--> Approval received" | |
exit 0 | |
else | |
echo "--> No approval found - cancelling workflow ..." | |
curl -L \ | |
-X POST \ | |
-H "Accept: application/vnd.github+json" \ | |
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ | |
-H "X-GitHub-Api-Version: 2022-11-28" \ | |
"https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/cancel" | |
echo "Workflow cancelled" | |
exit 1 | |
fi | |
deployment: | |
runs-on: ubuntu-latest | |
environment: | |
name: production | |
url: https://bctk.fullofstack.eu | |
env: | |
TF_LOG: DEBUG | |
# Scaleway credentials | |
TF_VAR_scaleway_access_key: ${{ secrets.SCALEWAY_ACCESS_KEY }} | |
TF_VAR_scaleway_secret_key: ${{ secrets.SCALEWAY_SECRET_KEY }} | |
TF_VAR_scaleway_organization_id: ${{ secrets.SCALEWAY_ORGANIZATION_ID }} | |
TF_VAR_scaleway_project_id: ${{ secrets.SCALEWAY_PROJECT_ID }} | |
TF_VAR_scaleway_server_user: ${{ secrets.SCALEWAY_SERVER_USER }} | |
TF_VAR_scaleway_ssh_pub_key_name: ${{ secrets.SCALEWAY_SSH_PUB_KEY_NAME }} | |
TF_VAR_scaleway_ssh_private_key: ${{ secrets.SCALEWAY_SSH_PRIVATE_KEY }} | |
TF_VAR_scaleway_zone: ${{ secrets.SCALEWAY_ZONE }} | |
# Data stored in Scaleway | |
TF_VAR_scaleway_awscli_config: ${{ secrets.SCALEWAY_AWSCLI_CONFIG }} | |
TF_VAR_data_bucket: ${{ secrets.DATA_BUCKET }} | |
TF_VAR_data_source: ${{ secrets.DATA_SOURCE }} | |
# Github secrets | |
TF_VAR_github_token: ${{ secrets.BCTK_GITHUB_TOKEN }} | |
TF_VAR_github_workspace: ${{ github.workspace }} | |
TF_VAR_github_repo_name: ${{ github.repository }} | |
# Terraform variables from variables.tf | |
TF_VAR_bctk_domain: ${{ secrets.BCTK_DOMAIN }} | |
TF_VAR_clickhouse_ip: ${{ secrets.CLICKHOUSE_IP }} | |
TF_VAR_clickhouse_port: ${{ secrets.CLICKHOUSE_PORT }} | |
TF_VAR_clickhouse_db: ${{ secrets.CLICKHOUSE_DB }} | |
TF_VAR_clickhouse_user: ${{ secrets.CLICKHOUSE_USER }} | |
TF_VAR_clickhouse_password: ${{ secrets.CLICKHOUSE_PASSWORD }} | |
TF_VAR_clickhouse_admin_user: ${{ secrets.CLICKHOUSE_ADMIN_USER }} | |
TF_VAR_clickhouse_admin_password: ${{ secrets.CLICKHOUSE_ADMIN_PASSWORD }} | |
TF_VAR_clickhouse_app_user: ${{ secrets.CLICKHOUSE_APP_USER }} | |
TF_VAR_clickhouse_app_password: ${{ secrets.CLICKHOUSE_APP_PASSWORD }} | |
# TF_VAR_data_path: "../data" | |
TF_VAR_avalanche_rpc_url: ${{ secrets.AVALANCHE_RPC_URL }} | |
needs: check-condition | |
if: ${{ needs.check-condition.outputs.RUN_DEPLOYMENT }} == 'true' | |
steps: | |
- name: Set Secrets for Pull Request | |
if: github.event_name == 'pull_request' | |
run: echo "TF_VAR_github_repo_branch=${{ github.head_ref }}" >> $GITHUB_ENV | |
- name: Set repository branch environment variable | |
run: | | |
if [ -z "${{ env.TF_VAR_github_repo_branch }}" ]; then | |
echo "TF_VAR_github_repo_branch is not set" | |
echo "TF_VAR_github_repo_branch=${{ github.ref_name }}" >> $GITHUB_ENV | |
fi | |
echo "TF_VAR_github_repo_branch is set to: ${{ env.TF_VAR_github_repo_branch }}" | |
- name: Checkout repository | |
uses: actions/[email protected] | |
- name: Delete deprecated Scaleway resources (DNS records & instance) | |
continue-on-error: true # when there is no instance to delete | |
run: | | |
# Install Scaleway CLI | |
ZONE=${{ secrets.SCALEWAY_ZONE }} | |
REGION="${ZONE:0:-2}" | |
echo 'Installing Scaleway CLI ...' | |
curl -s https://raw.githubusercontent.com/scaleway/scaleway-cli/master/scripts/get.sh | sh | |
mkdir -p ~/.config/scw | |
tee ~/.config/scw/config.yaml << EOF | |
access_key: ${{ secrets.SCALEWAY_ACCESS_KEY }} | |
secret_key: ${{ secrets.SCALEWAY_SECRET_KEY }} | |
default_organization_id: ${{ secrets.SCALEWAY_ORGANIZATION_ID }} | |
default_project_id: ${{ secrets.SCALEWAY_PROJECT_ID }} | |
default_zone: ${{ secrets.SCALEWAY_ZONE }} | |
default_region: $REGION | |
api_url: https://api.scaleway.com | |
EOF | |
# Delete previous DNS records | |
ROOT_DOMAIN=$(echo "$(echo ${{ secrets.BCTK_DOMAIN }} | cut -d'.' -f2).$(echo ${{ secrets.BCTK_DOMAIN }} | cut -d'.' -f3)") | |
SUB_DOMAIN=$(echo ${{ secrets.BCTK_DOMAIN }} | cut -d'.' -f1) | |
echo 'Deleting previous DNS records for '$SUB_DOMAIN' in '$ROOT_DOMAIN' ...' | |
scw dns record delete $ROOT_DOMAIN name=$SUB_DOMAIN type=A | |
scw dns record delete $ROOT_DOMAIN name=$SUB_DOMAIN type=AAAA | |
# Delete previous instance | |
scw instance server list project-id=${{ secrets.SCALEWAY_PROJECT_ID }} | |
INSTANCE_META=$(scw instance server list project-id=${{ secrets.SCALEWAY_PROJECT_ID }}) | |
INSTANCE_ID=$(echo "$INSTANCE_META" | awk 'NR==2 {print $1}') | |
INSTANCE_NAME=$(echo "$INSTANCE_META" | awk 'NR==2 {print $2}') | |
echo "Deleting instance '$INSTANCE_NAME' ..." | |
scw instance server stop "$INSTANCE_ID" | |
scw instance server wait "$INSTANCE_ID" | |
scw instance server delete "$INSTANCE_ID" with-volumes=all with-ip | |
- name: Set up Terraform | |
uses: hashicorp/[email protected] | |
- name: Initialize Terraform | |
uses: ./.github/actions/terraform | |
with: | |
command: init | |
- name: Terraform Format | |
uses: ./.github/actions/terraform | |
with: | |
command: fmt -check | |
- name: Terraform Plan | |
uses: ./.github/actions/terraform | |
with: | |
command: plan | |
- name: Apply Terraform configuration | |
uses: ./.github/actions/terraform | |
with: | |
command: apply -auto-approve |