← Back to Devlog
May 15, 2026 • DevOps & Security

Automating Zero-Secret Google Play Store Deployments via Workload Identity Federation

The Security Risk of Static Credentials: For many years, the standard approach to automating Google Play Store deployments inside GitHub Actions was to generate an Android Developer Service Account JSON key, encrypt it, and store it inside GitHub Repository Secrets. While convenient, this practice introduces significant security vectors. If a service account key is ever compromised, it grants indefinite API access until revoked. Furthermore, static credentials require regular rotation schedules, adding administrative overhead and risk of accidental pipeline failures.

The Solution - Workload Identity Federation (WIF): To establish a zero-secret deployment pipeline, we migrated our CI/CD architecture to Workload Identity Federation using OpenID Connect (OIDC). Instead of using a static, long-lived JSON key, GitHub Actions negotiates short-lived, single-use access tokens directly from Google Cloud Platform (GCP). The handshake is cryptographically verified against GitHub's trusted identity provider, ensuring that only specific workflows executing on authorized branches in our repository can act on behalf of the deployment service account.

Configuring the GCP Workload Identity Pool

First, we establish a dedicated Workload Identity Pool and OIDC provider on GCP. This provider is configured to trust assertions from GitHub's token authority. Run the following command via the gcloud CLI:

# Create the Workload Identity Pool
gcloud iam workload-identity-pools create "github-pool" \
    --location="global" \
    --description="Workload pool for GitHub Actions CI/CD" \
    --display-name="GitHub CI/CD Pool"

# Create the OIDC Provider inside the pool
gcloud iam workload-identity-pools providers create-oidc "github-provider" \
    --workload-identity-pool="github-pool" \
    --location="global" \
    --issuer-uri="https://token.actions.githubusercontent.com" \
    --attribute-mapping="google.subject=assertion.subject,attribute.actor=assertion.actor,attribute.repository=assertion.repository" \
    --display-name="GitHub Actions OIDC Provider"

Binding the Service Account to the Identity Pool

Next, we grant the GitHub Actions identity provider permission to impersonate our Play Store deployment service account. We restrict impersonation strictly to OIDC assertions matching our studio's specific repository and target branch:

# Authorize repository commits on the main branch to impersonate the service account
gcloud iam service-accounts add-iam-policy-binding "play-deployer@slopwair.iam.gserviceaccount.com" \
    --role="roles/iam.workloadIdentityUser" \
    --member="principalSet://iam.googleapis.com/projects/YOUR_PROJECT_NUM/locations/global/workloadIdentityPools/github-pool/attribute.repository/development-slopwair/SlopwAIr"

Implementing the GitHub Actions Workflow

Inside our deployment pipeline (.github/workflows/deploy-play-store.yml), we request write permissions for the ID token, verify authentication headlessly, and automatically upload the signed Android App Bundle (.aab) using official runner actions:

name: Deploy Android to Google Play

on:
  push:
    branches:
      - main

permissions:
  contents: read
  id-token: write

jobs:
  deploy:
    runs-on: ubuntu-26.04
    steps:
      - name: Checkout Source Code
        uses: actions/checkout@v4

      - name: Authenticate to Google Cloud via OIDC
        uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: 'projects/YOUR_PROJECT_NUM/locations/global/workloadIdentityPools/github-pool/providers/github-provider'
          service_account: 'play-deployer@slopwair.iam.gserviceaccount.com'

      - name: Upload Android App Bundle to Play Store
        uses: r0adkll/upload-google-play@v1
        with:
          packageName: com.slopwair.mazepoint
          releaseFiles: MazePoint-release.aab
          track: internal

By shifting to this modern OIDC token-based authentication model, we completely purged encrypted JSON credentials from our repository settings. The deployment pipeline is now cryptographically secured, audited, and strictly confined to verified GitHub execution runtimes.