# BEGIN INFORMATION

# DEPENDENCIES:
#
# `fish` - This uses `fish` syntax. It will not work under `bash` or `zsh`. Feel free to port it.
# `jq` - Used to parse JSON from `gh`.
# `gh` - GitHub CLI. Make sure this is installed and logged in.
# `gcloud` - Google Cloud CLI. Make sure this is installed and logged in.
#
# INSTRUCTIONS:
#
# 1. Edit the GCP and GitHub variables below.
# 2. Run this script in the repository you want to set up.

# BEGIN CONFIGURATION

# Define GCP-specific variables (edit these)
set -lx PROJECT "my-gcp-project"                    # Your GCP project ID
set -lx SERVICE_ACCOUNT_NAME "my-service-account"   # Name for the service account to create
set -lx IDENTITY_POOL_NAME "my-identity-pool"       # Name for the Workload Identity Pool
set -lx REGISTRY "region-docker.pkg.dev"            # Artifact Registry location
set -lx REPO_NAME "repo-name-with-dashes"           # Repository name in Artifact Registry

# Define GitHub-specific variables (edit these)
set -lx GITHUB_USER "my-github-username"             # Your GitHub username
set -lx GITHUB_REPO "my-repo-name"                   # Your GitHub repository name

# BEGIN DERIVED CONFIGURATION

# Derive additional variables from the ones defined above (no need to edit)
set -lx GITHUB_FULL_REPO "$GITHUB_USER/$GITHUB_REPO"                                    # Full GitHub repository path
set -lx PROVIDER_NAME "$IDENTITY_POOL_NAME-provider"                                    # Name for the identity provider
set -lx SERVICE_ACCOUNT_EMAIL "$SERVICE_ACCOUNT_NAME@$PROJECT.iam.gserviceaccount.com"  # Full service account email

# BEGIN SCRIPT LOGIC

# Enable required GCP services
gcloud services enable artifactregistry.googleapis.com      # For storing Docker images
gcloud services enable secretmanager.googleapis.com         # For managing secrets
gcloud services enable accesscontextmanager.googleapis.com  # For access control
gcloud services enable iamcredentials.googleapis.com        # For identity and access tokens

# Create a service account for GitHub Actions to use
gcloud iam service-accounts create "$SERVICE_ACCOUNT_NAME"

# Create a Workload Identity Pool for GitHub Actions
# This allows GitHub to authenticate as a GCP service account
gcloud iam workload-identity-pools create "$IDENTITY_POOL_NAME" \\
    --location="global" \\
    --display-name="$IDENTITY_POOL_NAME"

# Create an OIDC provider for the Workload Identity Pool
# This defines how GitHub Actions tokens will be validated and mapped to GCP identities
gcloud iam workload-identity-pools providers create-oidc "$PROVIDER_NAME" \\
    --location="global" \\
    --workload-identity-pool="$IDENTITY_POOL_NAME" \\
    --display-name="$PROVIDER_NAME" \\
    --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository" \\
    --attribute-condition="assertion.repository_owner=='$GITHUB_USER'" \\  # Only allow actions from repositories owned by this user
    --issuer-uri="<https://token.actions.githubusercontent.com/>"

# Allow the GitHub Action (via Workload Identity) to impersonate the service account
gcloud iam service-accounts add-iam-policy-binding "$SERVICE_ACCOUNT_EMAIL" \\
    --project="$PROJECT" \\
    --role="roles/iam.workloadIdentityUser" \\
    --member="principalSet://iam.googleapis.com/$IDENTITY_POOL_NAME/attribute.repository/$GITHUB_FULL_REPO"

# Grant the service account permission to manage artifacts in the registry
gcloud projects add-iam-policy-binding "$PROJECT" \\
    --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \\
    --role="roles/artifactregistry.admin"

# Get the full provider ID which will be needed for GitHub Actions workflow
set -lx PROVIDER_ID (gcloud iam workload-identity-pools providers describe "$PROVIDER_NAME" \\
                        --location="global" \\
                        --workload-identity-pool="$IDENTITY_POOL_NAME" \\
                        --format="value(name)")

# Set GitHub repository secrets for GCP authentication
gh secret set GCP_SERVICE_ACCOUNT --body "$SERVICE_ACCOUNT_EMAIL"           # Set service account email as a secret
gh secret set GCP_WORKLOAD_IDENTITY_PROVIDER --body "$PROVIDER_ID"          # Set provider ID as a secret

# Set GitHub repository variables for the workflow
gh variable set IMAGE_NAME --body (gh repo view --json name | jq .name)     # Set image name to repo name
gh variable set PROJECT --body "$PROJECT"                                   # Set GCP project ID
gh variable set REGISTRY --body "$REGISTRY"                                 # Set registry location
gh variable set REPO_NAME --body "$REPO_NAME"                               # Set repository name