diff --git a/.github/actions/argocd-deployment/argo-workflows-cli-wait/action.yaml b/.github/actions/argocd-deployment/argo-workflows-cli-wait/action.yaml new file mode 100644 index 00000000..131f22fc --- /dev/null +++ b/.github/actions/argocd-deployment/argo-workflows-cli-wait/action.yaml @@ -0,0 +1,40 @@ +--- +name: 'Argo Workflows CLI Wait for workflow' +description: 'Argo Workflows commands for its CLI wait for workflow.' + +inputs: + argo_namespace: + description: 'Argo Workflows namespace.' + required: false + default: 'argo-workflows' + argo_server: + description: 'Argo Workflows server URL.' + required: false + default: 'argo-workflows.stg.fcm.digital:443' + argo_token: + description: 'Argo Workflows auth token.' + required: true + environment: + description: 'Environment.' + required: true + labels: + description: 'Labels to be used for filtering.' + required: false + default: '' + +runs: + using: "composite" + steps: + - id: workflow-wait + name: 'Argo Workflow Wait' + shell: bash + run: ${{ github.action_path }}/entrypoint.sh + env: + ARGO_NAMESPACE: ${{ inputs.argo_namespace }} + ARGO_SERVER: ${{ inputs.argo_server }} + ARGO_TOKEN: ${{ inputs.argo_token }} + ARGO_HTTP1: true + ARGO_SECURE: true + KUBECONFIG: /dev/null + ENVIRONMENTS: ${{ inputs.environments }} + LABELS: ${{ inputs.labels }} \ No newline at end of file diff --git a/.github/actions/argocd-deployment/argo-workflows-cli-wait/entrypoint.sh b/.github/actions/argocd-deployment/argo-workflows-cli-wait/entrypoint.sh new file mode 100755 index 00000000..018f50db --- /dev/null +++ b/.github/actions/argocd-deployment/argo-workflows-cli-wait/entrypoint.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +set -euo pipefail + +if [[ -z $LABELS ]]; then + LABELS="" +else + LABELS="-l $LABELS" +fi + +echo "Waiting for Argo Workflow to complete" +argo wait @latest -n $ENVIRONMENTS $LABELS +if [[ $? -eq 0 ]]; then + echo "Argo Workflow submitted successfully" + argo get @latest -n $ENVIRONMENTS $LABELS +else + echo "Argo Workflow failed" + exit 1 +fi + diff --git a/.github/actions/github/execute-manual-workflow/action.yaml b/.github/actions/github/execute-manual-workflow/action.yaml new file mode 100644 index 00000000..f8a8998d --- /dev/null +++ b/.github/actions/github/execute-manual-workflow/action.yaml @@ -0,0 +1,93 @@ +--- +name: 'Execute Manual Workflow' +description: 'Execute a manual workflow based on .' + +inputs: + branch_name: + description: 'The branch name to execute the workflow on.' + required: false + default: "master" + github_token: + description: 'The GitHub Token. (Required if github_app_id and github_app_private_key are not provided)' + required: true + github_organization_name: + description: 'The GitHub organization name.' + required: true + github_repository_name: + description: 'The repository name.' + required: true + workflow_id: + description: 'The workflow ID.' + required: true + workflow_inputs: + description: 'The workflow inputs. Valid format: "--field key1=value1 --field key2=value2"' + required: false + default: "" + workflow_watch: + description: 'Whether to watch the workflow run or not. If true, the workflow will wait for the new workflow to finish.' + required: false + default: "false" + # This input is necessary because `gh workflow run` doesn't return the database ID of the workflow run and `gh run watch` requires the database ID. + workflow_watch_name_filter: + description: 'Filter the workflow run by name (Only available if workflow_watch is true).' + required: false + default: "" + workflow_watch_user: + description: 'The user to watch the workflow run as (Only available if workflow_watch is true).' + required: false + default: "" + +runs: + using: "composite" + steps: + - id: exec-workflow + name: Execute Workflow + env: + GH_TOKEN: ${{ inputs.github_token }} + run: | + gh workflow run ${{ inputs.workflow_id }} --repo ${{ inputs.github_organization_name }}/${{ inputs.github_repository_name }} --ref ${{ inputs.branch_name }} ${{ inputs.workflow_inputs }} + shell: bash + + - id: watch-workflow + if: inputs.workflow_watch == 'true' + name: Watch Workflow + env: + GH_TOKEN: ${{ inputs.github_token }} + GH_OUTPUT_FILE_NAME: gh-output.json + run: | + echo "Waiting for new run to appear..." + for i in {1..12}; do + sleep 10 + # Get the latest run of the workflow as the user specified + gh run list --workflow=${{ inputs.workflow_id }} --repo ${{ inputs.github_organization_name }}/${{ inputs.github_repository_name }} --limit=1 --user "${{ inputs.workflow_watch_user }}" --json name,databaseId,createdAt > $GH_OUTPUT_FILE_NAME + + if [[ $? -ne 0 ]] || [ ! -f "$GH_OUTPUT_FILE_NAME" ] && [ ! -s "$GH_OUTPUT_FILE_NAME" ]; then + echo "Workflow run not found. Still waiting... ($i/12)" + continue + fi + + WORKFLOW_RUN_TIMESTAMP=$(cat $GH_OUTPUT_FILE_NAME | jq '.[0].createdAt' | xargs -I {} date -d {} +%s) + CURRENT_TIMESTAMP=$(date +%s) + + WORKFLOW_RUN_AGE=$((CURRENT_TIMESTAMP - WORKFLOW_RUN_TIMESTAMP)) + if [[ $WORKFLOW_RUN_AGE -lt 120 ]]; then + echo "Workflow run found with age of $WORKFLOW_RUN_AGE seconds" + + # Get the database ID of the workflow run + WORKFLOW_RUN_DBID=$(cat $GH_OUTPUT_FILE_NAME | jq --arg name "${{ inputs.workflow_watch_name_filter }}" '.[] | select(.name | contains($name))' | jq '.databaseId') + + if [[ -z "$WORKFLOW_RUN_DBID" ]]; then + echo "Workflow run not found. Still waiting... ($i/12)" + continue + fi + echo "Workflow run found with database ID: $WORKFLOW_RUN_DBID" + break + else + echo "Workflow run not found. Still waiting... ($i/12)" + continue + fi + done + + # Wait for the workflow to finish and exit with the same status. + gh run watch --repo ${{ inputs.github_organization_name }}/${{ inputs.github_repository_name }} $WORKFLOW_RUN_DBID --interval 15 --compact --exit-status + shell: bash \ No newline at end of file diff --git a/.github/actions/github/generate-github-app-token/action.yaml b/.github/actions/github/generate-github-app-token/action.yaml new file mode 100644 index 00000000..ef1122d7 --- /dev/null +++ b/.github/actions/github/generate-github-app-token/action.yaml @@ -0,0 +1,46 @@ +--- +name: 'Generate GitHub App Token' +description: 'Generate a GitHub App token based on the GitHub App ID and private key.' + +inputs: + github_app_id: + description: 'The GitHub App ID.' + required: true + github_app_private_key: + description: 'The GitHub App private key.' + required: true + github_organization_name: + description: 'The GitHub organization name.' + required: true + github_repositories: + description: 'The GitHub repositories names to grant access to.' + required: true + +outputs: + gh_token: + description: 'The GitHub App token.' + value: ${{ steps.generate-gh-token.outputs.token }} + +runs: + using: "composite" + steps: + - name: Generate a GH Token + id: generate-gh-token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ inputs.github_app_id }} + private-key: ${{ inputs.github_app_private_key }} + owner: ${{ inputs.github_organization_name }} + repositories: ${{ inputs.github_repositories }} + + - name: Test Token + run: | + gh auth status + if [[ $? -ne 0 ]]; then + echo "Failed to get GitHub App Token using GH App ID: ${{ inputs.github_app_id }} credentials." + exit 1 + else + echo "GitHub App Token generated successfully. Token saved to output 'gh_token'." + fi + shell: bash + \ No newline at end of file diff --git a/.github/actions/github/get-workflow-id/action.yaml b/.github/actions/github/get-workflow-id/action.yaml new file mode 100644 index 00000000..1cf0a0ce --- /dev/null +++ b/.github/actions/github/get-workflow-id/action.yaml @@ -0,0 +1,47 @@ +--- +name: 'Get Workflow ID' +description: 'Get the ID of a GitHub workflow based on the workflow file name and repository.' + +inputs: + github_token: + description: 'The GitHub Token.' + required: true + github_organization_name: + description: 'The GitHub organization name.' + required: true + github_repository_name: + description: 'The repository name.' + required: true + workflow_file_name: + description: 'The workflow file name.' + required: true + +outputs: + workflow_id: + description: 'The workflow ID.' + value: ${{ steps.get-workflow-id.outputs.workflow_id }} + +runs: + using: "composite" + steps: + - id: get-workflow-id + name: Get Workflow ID + env: + GH_TOKEN: ${{ inputs.github_token }} + GH_OUTPUT_FILE_NAME: gh-output.json + run: | + gh workflow list --repo ${{ inputs.github_organization_name }}/${{ inputs.github_repository_name }} --json id,path > $GH_OUTPUT_FILE_NAME + + if [[ $? -ne 0 ]] || [ ! -f "$GH_OUTPUT_FILE_NAME" ] && [ ! -s "$GH_OUTPUT_FILE_NAME" ]; then + echo "Failed to list workflows" + exit 1 + fi + + WORKFLOW_ID=$(cat $GH_OUTPUT_FILE_NAME | jq --arg workflowFileName "${{ inputs.workflow_file_name }}" '.[] | select(.path | contains($workflowFileName))' | jq '.id') + + if [[ $? -ne 0 ]] || [[ -z $WORKFLOW_ID ]]; then + echo "Failed to get workflow ID" + exit 1 + fi + echo "workflow_id=$WORKFLOW_ID" >> $GITHUB_OUTPUT + shell: bash \ No newline at end of file diff --git a/.github/actions/google-cloud-platform/cloudsql-instance-new-owner/action.yaml b/.github/actions/google-cloud-platform/cloudsql-instance-new-owner/action.yaml new file mode 100644 index 00000000..a772d966 --- /dev/null +++ b/.github/actions/google-cloud-platform/cloudsql-instance-new-owner/action.yaml @@ -0,0 +1,101 @@ +--- +name: 'CloudSQL Instance New Owner' +description: 'Reassign the owner of a CloudSQL instance to a new owner.' + +inputs: + gcloud-sdk-configure: + description: 'Whether to configure GCloud SDK.' + required: false + default: 'false' + gcp-project-id: + description: 'The GCP project ID.' + required: true + + app-name: + description: 'The name of the application.' + required: true + service-name: + description: 'The name of the specific service (part of the app-name).' + required: true + database-name: + description: 'The prefix name of the database.' + required: true + + restore-environment: + description: 'The environment to which the instance is being restored.' + required: true + snapshot-environment: + description: 'The environment from which the snapshot was taken.' + required: true + + restore-instance: + description: 'The CloudSQL instance ID to reassign the owner of.' + required: true + private-ip-instance: + description: 'The CloudSQL private IP of the restored instance.' + required: true + + postgres-user-pwd: + description: 'The password for the PostgreSQL database.' + required: true + appname-user-pwd: + description: 'The password for the App User.' + required: true + +runs: + using: "composite" + steps: + - id: gcloud-sdk-configure + if: inputs.gcloud-sdk-configure == 'true' + name: 'Configure GCloud SDK' + uses: fcm-digital/.github/.github/actions/google-cloud-platform/gcloud-sdk-configure@sc-23004-dynamic-staging-envs + with: + gcp-project-id: ${{ inputs.gcp-project-id }} + + - id: restore-postgres-user-password + name: Restore Postgres User Password + env: + DESTINATION_INSTANCE_ID: ${{ inputs.restore-instance }} + PGUSER: 'postgres' + PGPASSWORD: ${{ inputs.postgres-user-pwd }} + shell: bash + run: gcloud sql users set-password "${PGUSER}" --instance="${DESTINATION_INSTANCE_ID}" --password=${PGPASSWORD} --project=${{ inputs.gcp-project-id }} + + - id: create-app-user + name: 'Create database user and password' + env: + DESTINATION_INSTANCE_ID: ${{ inputs.restore-instance }} + PGUSER: '${{ inputs.service-name }}-${{ inputs.restore-environment }}' + PGPASSWORD: ${{ inputs.appname-user-pwd }} + shell: bash + run: gcloud sql users create "${PGUSER}" --instance="${DESTINATION_INSTANCE_ID}" --password=${PGPASSWORD} --project=${{ inputs.gcp-project-id }} + + - id: install-psql + name: Install PostgreSQL Client + shell: bash + run: | + sudo apt-get update + sudo apt-get install --yes --no-install-recommends postgresql-client + + - id: 'run-postgres-config' + name: 'Configure restored PostgreSQL database' + env: + PGPASSWORD: ${{ inputs.postgres-user-pwd }} + shell: bash + run: |- + psql --host=${{ inputs.private-ip-instance }} --port=5432 --username=postgres < + 'The ID of the snapshot to restore. + (If not provided, the process will restore the last snapshot from the snapshot-instance)' + required: false + +runs: + using: "composite" + steps: + - id: gcloud-sdk-configure + if: inputs.gcloud-sdk-configure == 'true' + name: 'Configure GCloud SDK' + uses: fcm-digital/.github/.github/actions/google-cloud-platform/gcloud-sdk-configure@sc-23004-dynamic-staging-envs + with: + gcp-project-id: ${{ inputs.gcp-project-id }} + + - id: get-last-snapshot + name: 'Get Last Snapshot' + shell: bash + run: | + if [[ -z '${{ inputs.snapshot-id }}' ]]; then + echo "No Snapshot ID provided, getting last snapshot from ${{ inputs.snapshot-instance }}..." + LAST_INSTANCE_BACKUP=$(gcloud sql backups list --instance=${{ inputs.snapshot-instance }} --filter="STATUS:(SUCCESSFUL)" --project=${{ inputs.gcp-project-id }} --limit=1 | tail -n 1 | awk '{print $1}') + if [ $? -ne 0 ] && [ -z "$LAST_INSTANCE_BACKUP" ]; then + echo "Failed to get last backup for CloudSQL instance: $SNAPSHOT_FROM" + exit 1 + fi + else + LAST_INSTANCE_BACKUP=${{ inputs.snapshot-id }} + fi + echo "Last backup for CloudSQL instance ${{ inputs.snapshot-instance }}: $LAST_INSTANCE_BACKUP" + echo "last_instance_backup=$LAST_INSTANCE_BACKUP" >> $GITHUB_ENV + + - id: restore-snapshot + name: 'Restore Snapshot' + shell: bash + run: | + echo "Restoring CloudSQL instance ${{ inputs.restore-instance }} using backup: ${{ env.last_instance_backup }} from ${{ inputs.snapshot-instance }}..." + gcloud sql backups restore ${{ env.last_instance_backup }} --restore-instance=${{ inputs.restore-instance }} --backup-instance=${{ inputs.snapshot-instance }} --project=${{ inputs.gcp-project-id }} + if [ $? -ne 0 ]; then + echo "Failed to restore CloudSQL instance: ${{ inputs.restore-instance }}" + exit 1 + fi + echo "CloudSQL instance ${{ inputs.restore-instance }} restored successfully." diff --git a/.github/actions/google-cloud-platform/cloudsql-start-instance/action.yaml b/.github/actions/google-cloud-platform/cloudsql-start-instance/action.yaml new file mode 100644 index 00000000..c56dc4e7 --- /dev/null +++ b/.github/actions/google-cloud-platform/cloudsql-start-instance/action.yaml @@ -0,0 +1,36 @@ +name: 'CloudSQL Start Instance' +description: 'Start a CloudSQL instance.' + +inputs: + gcloud-sdk-configure: + description: 'Whether to configure GCloud SDK.' + required: false + default: 'false' + gcp-project-id: + description: 'The GCP project ID.' + required: true + instance: + description: 'The CloudSQL instance to start.' + required: true + +runs: + using: "composite" + steps: + - id: gcloud-sdk-configure + if: inputs.gcloud-sdk-configure == 'true' + name: 'Configure GCloud SDK' + uses: fcm-digital/.github/.github/actions/google-cloud-platform/gcloud-sdk-configure@sc-23004-dynamic-staging-envs + with: + gcp-project-id: ${{ inputs.gcp-project-id }} + + - id: start-instance + name: 'Start CloudSQL Instance' + shell: bash + run: | + echo "Starting CloudSQL instance...: ${{ inputs.instance }}" + gcloud sql instances patch ${{ inputs.instance }} --activation-policy=ALWAYS --project=${{ inputs.gcp-project-id }} + if [ $? -ne 0 ]; then + echo "Failed to start CloudSQL instance: ${{ inputs.instance }}" + exit 1 + fi + echo "CloudSQL instance ${{ inputs.instance }} started successfully." diff --git a/.github/actions/google-cloud-platform/gcloud-sdk-configure/action.yaml b/.github/actions/google-cloud-platform/gcloud-sdk-configure/action.yaml new file mode 100644 index 00000000..aa242e76 --- /dev/null +++ b/.github/actions/google-cloud-platform/gcloud-sdk-configure/action.yaml @@ -0,0 +1,128 @@ +--- +name: 'Configure GCloud SDK' +description: 'Configure gcloud SDK based on the inputs provided.' + +inputs: + checkout-local-repository: + description: 'Whether to checkout the local repository.' + required: false + default: 'true' + configure-gke: + description: 'Whether to configure GKE.' + required: false + default: 'false' + + gcp-json: + description: 'The Service Account that contains the permissions to GCP.' + required: false + default: '' + + gcp-wif-project-id: + description: 'The GCP project ID to use for WIF authentication.' + required: false + default: '896400447443' #fcm-platform-stg-a3dc project + gcp-wif-pool: + description: 'The GCP WIF Pool to use for authentication.' + required: false + default: 'dynamic-staging-envs' + gcp-wif-provider: + description: 'The GCP WIF Provider to use for authentication.' + required: false + default: 'github-actions' + gcp-wif-service-account: + description: 'The GCP SA to use for authentication.' + required: false + default: 'dynamic-staging-envs@fcm-platform-stg-a3dc.iam.gserviceaccount.com' + + gcp-project-id: + description: 'The GCP project ID. If provided, this will configure gcloud to use this project ID by default for commands.' + required: false + default: 'fcm-platform-stg-a3dc' #fcmp-stg project + gcloud-version: + description: 'The gcloud version to use.' + required: false + default: '522.0.0' + gcloud-command: + description: 'The gcloud command to execute.' + required: true + + # ----------------------------- + # Additional configurations + # ----------------------------- + + # Kubectl + install-kubectl: + description: 'Whether to install kubectl.' + required: false + default: 'true' + kubectl-version: + description: 'The version of kubectl to install.' + required: false + default: 'v1.33.1' + + cluster-name: + description: 'The name of the GKE cluster.' + required: false + default: 'fcm-platform-stg-euw1' + location: + description: 'The location of the GKE cluster.' + required: false + default: 'europe-west1' + + +runs: + using: "composite" + steps: + - id: checkout + if: inputs.checkout-local-repository + name: Checkout Local Repository + uses: actions/checkout@v4 + + - id: setup-gcp-credentials + if: inputs.gcp-json != '' + name: 'Set Up Google Credentials' + uses: google-github-actions/auth@v2 + with: + credentials_json: ${{ inputs.gcp-json }} + project_id: ${{ inputs.gcp-project-id }} + + - id: auth-gcp-wif + if: inputs.gcp-json == '' + name: Authenticate to GCP via WIF + uses: google-github-actions/auth@v2 + with: + token_format: "access_token" + workload_identity_provider: "projects/${{ inputs.gcp-wif-project-id }}/locations/global/workloadIdentityPools/${{ inputs.gcp-wif-pool }}/providers/${{ inputs.gcp-wif-provider }}" + service_account: ${{ inputs.gcp-wif-service-account }} + + - id: generate-sdk-components + name: 'Generate SDK Components' + shell: bash + run: | + SDK_COMPONENTS='' + if [ '${{ inputs.configure-gke }}' == 'true' ]; then + SDK_COMPONENTS+='gke-gcloud-auth-plugin,' + fi + echo "install_components=$(echo "$SDK_COMPONENTS" | sed 's/,$//')" >> $GITHUB_ENV + + - id: setup-gcloud-sdk + name: 'Set up Cloud SDK' + uses: 'google-github-actions/setup-gcloud@v2' + with: + version: '>= ${{ inputs.gcloud-version }}' + project_id: ${{ inputs.gcp-project-id }} + install_components: ${{ env.install_components }} + + - id: get-credentials + if: inputs.configure-gke == 'true' + name: 'Get GKE Credentials' + uses: 'google-github-actions/get-gke-credentials@v2' + with: + cluster_name: ${{ inputs.cluster-name }} + location: ${{ inputs.location }} + + - id: install-kubectl + if: inputs.install-kubectl == 'true' && inputs.configure-gke == 'true' + uses: azure/setup-kubectl@v4 + with: + version: ${{ inputs.kubectl-version }} \ No newline at end of file diff --git a/.github/actions/infrastructure/execute-terragrunt/action.yaml b/.github/actions/infrastructure/execute-terragrunt/action.yaml new file mode 100644 index 00000000..b353d30f --- /dev/null +++ b/.github/actions/infrastructure/execute-terragrunt/action.yaml @@ -0,0 +1,187 @@ +--- +name: 'Execute Terragrunt' +description: 'Execute terragrunt command based on the inputs provided.' + +inputs: + gcp_wif_project_id: + description: 'The GCP project ID to use for WIF authentication.' + required: false + default: '896400447443' #fcm-platform-stg-a3dc project + gcp_wif_pool: + description: 'The GCP WIF Pool to use for authentication.' + required: false + default: 'dynamic-staging-envs' + gcp_wif_provider: + description: 'The GCP WIF Provider to use for authentication.' + required: false + default: 'github-actions' + gcp_wif_service_account: + description: 'The GCP SA to use for authentication.' + required: false + default: 'dynamic-staging-envs@fcm-platform-stg-a3dc.iam.gserviceaccount.com' + + github_token: + description: 'The GitHub token.' + required: true + argocd_host: + description: 'The ArgoCD host.' + required: false + default: 'argocd-server.argocd.svc.cluster.local:443' + argocd_token: + description: 'The ArgoCD token.' + required: true + openpassword_host: + description: 'The 1Password host.' + required: false + default: 'http://onepassword-connect.1password-connect.svc.cluster.local:8080' + onepassword_token: + description: 'The 1Password token.' + required: true + + terragrunt_path: + description: 'The terragrunt path to the target resources.' + required: true + terragrunt_command: + description: > + The terragrunt command to run. Valid values are: `apply`, `outputs` or `destroy`. + - `apply`: Apply the terragrunt resources. + - `output`: Output the terragrunt resources to the file specified by `terragrunt_output_file_name`. + - `destroy`: Destroy the specific terragrunt resources. + required: true + terragrunt_command_vars: + description: 'The variables to pass to the terragrunt command.' + required: false + terragrunt_output_file_name: + description: 'The name of the file to output the terragrunt outputs to.' + required: false + default: 'tg-outputs.json' + + terragrunt_version: + description: 'The terragrunt version to use.' + required: true + terraform_version: + description: 'The terraform version to use.' + required: false + default: '' + opentofu_version: + description: 'The opentofu version to use.' + required: false + default: '' + + +outputs: + cloudsql_instances: + description: 'The CloudSQL instances names.' + value: ${{ steps.get-tg-outputs.outputs.cloudsql_instances }} + redis_instances: + description: 'The Redis instances names.' + value: ${{ steps.get-gcp-resource-names.outputs.redis_instances }} + gcp_region: + description: 'The GCP region.' + value: ${{ steps.get-gcp-resource-names.outputs.gcp_region }} + gcp_zone: + description: 'The GCP zone.' + value: ${{ steps.get-gcp-resource-names.outputs.gcp_zone }} + + +runs: + using: "composite" + steps: + - id: setup-versions + name: Setup versions + shell: bash + run: | + if [ -z "${{ inputs.terraform_version }}" && -z "${{ inputs.opentofu_version }}" ]; then + echo "error: terraform_version or opentofu_version is required" + exit 1 + fi + + INPUT_COMMANDS=$(echo "${{ inputs.terragrunt_command_vars }}" | tr '\n' ' ') + if [ ! -z "$INPUT_COMMANDS" ]; then + for var in $INPUT_COMMANDS; do + COMMAND_VARS+="-var $var " + done + echo "command_vars=$COMMAND_VARS" >> $GITHUB_ENV + fi + + - id: checkout-infrastructure-repository + name: Checkout Infrastructure Repository + uses: actions/checkout@v4 + with: + repository: fcm-digital/infrastructure + ref: dynamic-performance-env #ToDo: update to `main` when PR is merged + path: infrastructure + token: ${{ inputs.github_token }} + + - id: auth-gcp-wif + name: Authenticate to GCP via WIF + uses: google-github-actions/auth@v2 + with: + token_format: "access_token" + workload_identity_provider: "projects/${{ inputs.gcp_wif_project_id }}/locations/global/workloadIdentityPools/${{ inputs.gcp_wif_pool }}/providers/${{ inputs.gcp_wif_provider }}" + service_account: ${{ inputs.gcp_wif_service_account }} + + - id: terragrunt-plan + if: inputs.terragrunt_command == 'plan' + name: Terragrunt Plan + uses: gruntwork-io/terragrunt-action@v2 + env: + INPUT_PRE_EXEC_1: | + git config --global url."https://x-access-token:${{ inputs.github_token }}@github.com/fcm-digital/".insteadOf "ssh://git@github.com/fcm-digital/" + git config --global url."https://github.com/".insteadOf "ssh://git@github.com/" + TG_NON_INTERACTIVE: true + OP_CONNECT_HOST: ${{ inputs.openpassword_host }} + OP_CONNECT_TOKEN: ${{ inputs.onepassword_token }} + ARGOCD_SERVER: ${{ inputs.argocd_host }} + ARGOCD_AUTH_TOKEN: ${{ inputs.argocd_token }} + with: + tg_version: ${{ inputs.terragrunt_version }} + tf_version: ${{ inputs.terraform_version || null }} + tofu_version: ${{ inputs.opentofu_version || null }} + tg_dir: ${{ inputs.terragrunt_path }} + tg_add_approve: 0 + tg_command: plan ${{ env.command_vars }} + + - id: terragrunt-apply + if: inputs.terragrunt_command == 'apply' + name: Terragrunt Apply + uses: gruntwork-io/terragrunt-action@v2 + env: + INPUT_PRE_EXEC_1: | + git config --global url."https://x-access-token:${{ inputs.github_token }}@github.com/fcm-digital/".insteadOf "ssh://git@github.com/fcm-digital/" + git config --global url."https://github.com/".insteadOf "ssh://git@github.com/" + TG_NON_INTERACTIVE: true + OP_CONNECT_HOST: ${{ inputs.openpassword_host }} + OP_CONNECT_TOKEN: ${{ inputs.onepassword_token }} + ARGOCD_SERVER: ${{ inputs.argocd_host }} + ARGOCD_AUTH_TOKEN: ${{ inputs.argocd_token }} + with: + tg_version: ${{ inputs.terragrunt_version }} + tf_version: ${{ inputs.terraform_version || null }} + tofu_version: ${{ inputs.opentofu_version || null }} + tg_dir: ${{ inputs.terragrunt_path }} + tg_add_approve: 1 + tg_command: apply ${{ env.command_vars }} + + - id: terragrunt-outputs + if: inputs.terragrunt_command == 'outputs' + name: Terragrunt Outputs + uses: gruntwork-io/terragrunt-action@v2 + env: + INPUT_PRE_EXEC_1: | + git config --global url."https://x-access-token:${{ inputs.github_token }}@github.com/fcm-digital/".insteadOf "ssh://git@github.com/fcm-digital/" + git config --global url."https://github.com/".insteadOf "ssh://git@github.com/" + INPUT_POST_EXEC_1: | + terragrunt output -json > ${{ inputs.terragrunt_output_file_name }} + TG_NON_INTERACTIVE: true + OP_CONNECT_HOST: ${{ inputs.openpassword_host }} + OP_CONNECT_TOKEN: ${{ inputs.onepassword_token }} + ARGOCD_SERVER: ${{ inputs.argocd_host }} + ARGOCD_AUTH_TOKEN: ${{ inputs.argocd_token }} + with: + tg_version: ${{ inputs.terragrunt_version }} + tf_version: ${{ inputs.terraform_version || null }} + tofu_version: ${{ inputs.opentofu_version || null }} + tg_dir: ${{ inputs.terragrunt_path }} + tg_add_approve: 0 + tg_command: init ${{ env.command_vars }} diff --git a/.github/actions/k6/configure-k6/action.yaml b/.github/actions/k6/configure-k6/action.yaml new file mode 100644 index 00000000..7f4a18a1 --- /dev/null +++ b/.github/actions/k6/configure-k6/action.yaml @@ -0,0 +1,38 @@ +--- +name: 'Configure k6' +description: 'Configure k6 for performance testing.' + +inputs: + k6-version: + description: 'The version of k6 to use.' + required: false + default: 'latest' + + dd-api-key: + description: 'The DataDog API key to use. (Leave empty to disable DataDog integration.)' + required: true + dd-languages: + description: 'The languages to use for DataDog integration.' + required: true + dd-site: + description: 'The DataDog site to use.' + required: false + default: 'app.datadoghq.eu' + +runs: + using: "composite" + steps: + - id: setup-k6 + name: Setup k6 + uses: grafana/setup-k6-action@v1 + with: + k6-version: ${{ inputs.k6-version }} + + - id: setup-dd-agent + if: inputs.dd-api-key != '' + name: Configure Datadog Test Optimization + uses: datadog/test-visibility-github-action@v2 + with: + languages: ${{ inputs.dd-languages }} + api_key: ${{ inputs.dd-api-key }} + site: ${{ inputs.dd-site }}