Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
yasserstudio avatar

Gpc Ci Integration

  • 24 installs
  • 1 repo stars
  • Updated August 1, 2026
  • yasserstudio/gpc-skills

Helps with ai & agent building tasks.

About

gpc-ci-integration is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.

  • gpc-ci-integration
  • AI & Agent Building
  • AI-coding skill

Gpc Ci Integration by the numbers

  • 24 all-time installs (skills.sh)
  • +1 installs in the week ending Jul 27, 2026 (Skillselion tracking)
  • Ranked #9,876 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/yasserstudio/gpc-skills --skill gpc-ci-integration

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs24
repo stars1
Last updatedAugust 1, 2026
Repositoryyasserstudio/gpc-skills

What it does

Helps with ai & agent building tasks.

Files

SKILL.mdMarkdownGitHub ↗

GPC CI Integration

When to use

Use this skill when the task involves:

  • Setting up GPC in GitHub Actions, GitLab CI, Bitbucket Pipelines, or CircleCI
  • Automating Play Store releases from CI/CD
  • Configuring environment variables for CI authentication
  • Using GPC's JSON output for scripting and automation
  • Implementing vitals-gated rollouts in CI
  • Building release pipelines with upload → promote → monitor flows
  • Using --dry-run for safe CI testing

Inputs required

  • CI platform (GitHub Actions, GitLab CI, Bitbucket, CircleCI, or generic)
  • Auth method (usually service account via env var)
  • Release workflow: upload only, upload + promote, or full pipeline
  • Whether vitals gating is desired
  • Package name of the Android app

Procedure

Quickest path: GPC GitHub Action (v0.9.81+)

For GitHub Actions users, the GPC GitHub Action is the fastest way to publish to the Play Store. No Node.js setup step, no manual install, no wrapper script.

Available on the GitHub Actions Marketplace.

Minimal usage:

- uses: yasserstudio/gpc-action@v1
  with:
    service-account-json: ${{ secrets.GPC_SERVICE_ACCOUNT }}
    package-name: com.example.app
    release-file: app/build/outputs/bundle/release/app-release.aab
    track: internal

One step replaces the full install + run + cleanup sequence. The action runs a built-in preflight compliance gate before uploading, so non-compliant AABs are rejected before they reach the Play API.

Migrating from `r0adkll/upload-google-play`? It is a drop-in replacement. The input names are the same; change one line:

# Before:
- uses: r0adkll/upload-google-play@v1

# After:
- uses: yasserstudio/gpc-action@v1

The action is a TypeScript action running on Node 24. No additional configuration is required for the migration.

For advanced pipelines (multi-step, vitals gating, changelog generation), continue with the manual workflow patterns below.

0) CI environment behavior

GPC auto-detects CI environments:

  • Output: Defaults to JSON when stdout is not a TTY (piped or CI)
  • Interactive: Prompts are disabled automatically when CI=true
  • Colors: Disabled in non-TTY environments
  • Plugin-CI: Writes GitHub Actions step summaries when $GITHUB_STEP_SUMMARY is available

Environment variables for CI override:

GPC_NO_INTERACTIVE=1   # Explicitly disable prompts
GPC_NO_COLOR=1         # Explicitly disable colors
GPC_OUTPUT=json        # Force JSON output

Config resolution precedence (v0.9.81+): CLI flags override env vars, which override the active profile, which overrides .gpcrc.json, which falls back to defaults.

--service-account / --app flags  (highest priority)
  GPC_SERVICE_ACCOUNT / GPC_APP env vars
    active profile (gpc auth switch <name>)
      .gpcrc.json
        defaults

Prior to v0.9.81, an active profile silently won over GPC_SERVICE_ACCOUNT/GPC_APP env vars. This is now fixed. If your CI sets GPC_SERVICE_ACCOUNT and a profile is also active, the env var takes effect as expected.

1) GitHub Actions

Minimal — upload to internal track:
name: Upload to Play Store
on:
  push:
    tags: ['v*']
  workflow_dispatch: {}

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build AAB
        run: ./gradlew bundleRelease

      - name: Install GPC
        run: npm install -g @gpc-cli/cli --ignore-scripts

      - name: Upload to Play Store
        env:
          GPC_SERVICE_ACCOUNT: ${{ secrets.PLAY_SERVICE_ACCOUNT }}
          GPC_APP: com.example.app
        run: |
          gpc releases upload app/build/outputs/bundle/release/app-release.aab \
            --track internal \
            --changes-not-sent-for-review
Full pipeline — upload, check vitals, promote:
name: Release Pipeline
on:
  workflow_dispatch:
    inputs:
      track:
        description: 'Target track'
        default: 'beta'
      rollout:
        description: 'Rollout percentage'
        default: '100'

jobs:
  release:
    runs-on: ubuntu-latest
    env:
      GPC_APP: com.example.app
    steps:
      - uses: actions/checkout@v4

      - name: Install GPC
        run: npm install -g @gpc-cli/cli --ignore-scripts

      - name: Preflight compliance check
        run: gpc preflight app-release.aab --fail-on error --json

      - name: Upload release
        env:
          GPC_SERVICE_ACCOUNT: ${{ secrets.PLAY_SERVICE_ACCOUNT }}
        run: |
          gpc releases upload app-release.aab \
            --track ${{ inputs.track }} \
            --rollout ${{ inputs.rollout }} \
            --changes-not-sent-for-review \
            --mapping-type PROGUARD \
            --device-tier-config default

      - name: Error if in review
        env:
          GPC_SERVICE_ACCOUNT: ${{ secrets.PLAY_SERVICE_ACCOUNT }}
        run: gpc releases status --error-if-in-review

      - name: Check vitals
        if: inputs.track == 'production'
        env:
          GPC_SERVICE_ACCOUNT: ${{ secrets.PLAY_SERVICE_ACCOUNT }}
        run: |
          gpc vitals crashes --threshold 2.0
          gpc vitals anr --threshold 0.47

      - name: Release status
        if: always()
        env:
          GPC_SERVICE_ACCOUNT: ${{ secrets.PLAY_SERVICE_ACCOUNT }}
        run: gpc releases status --output markdown >> $GITHUB_STEP_SUMMARY

      - name: Generate GitHub Release notes
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: gpc changelog generate | gh release create ${{ github.ref_name }} -F -
        # Requires GPC v0.9.61+. --strict flag available to fail CI on jargon.

Read:

  • references/github-actions.md

2) GitLab CI

release:
  image: node:22
  stage: deploy
  variables:
    GPC_SERVICE_ACCOUNT: $PLAY_SERVICE_ACCOUNT
    GPC_APP: com.example.app
  script:
    - npm install -g @gpc-cli/cli
    - gpc releases upload app-release.aab --track internal --changes-not-sent-for-review
  only:
    - tags

3) Bitbucket Pipelines

pipelines:
  tags:
    'v*':
      - step:
          name: Upload to Play Store
          image: node:22
          script:
            - npm install -g @gpc-cli/cli
            - gpc releases upload app-release.aab --track internal --changes-not-sent-for-review
          deployment: production

4) CircleCI

jobs:
  release:
    docker:
      - image: cimg/node:22.0
    steps:
      - checkout
      - run:
          name: Upload to Play Store
          command: |
            npm install -g @gpc-cli/cli
            gpc releases upload app-release.aab --track internal --changes-not-sent-for-review
          environment:
            GPC_APP: com.example.app

5) Using standalone binary (no Node.js)

For minimal CI images without Node.js:

- name: Install GPC binary
  run: curl -fsSL https://raw.githubusercontent.com/yasserstudio/gpc/main/scripts/install.sh | bash

- name: Upload
  run: gpc releases upload app-release.aab --track internal

6) Output formats for CI scripting

GPC auto-outputs JSON in CI (non-TTY). Parse with jq:

JUnit output caveat: --output junit is available but testcase name attributes use generic identifiers (item-1, item-2) for some commands (tracks list, releases status). Prefer --output json | jq for reliable CI parsing. Use --output junit only if your test reporter specifically requires JUnit XML format.

CSV/TSV output (v0.9.68+): All commands support --output csv and --output tsv for spreadsheet-friendly or tab-delimited parsing without requiring jq:

# Export release status as CSV (headers on first line)
gpc releases status --output csv > releases.csv

# TSV for awk / cut parsing in shell scripts
gpc vitals crashes --output tsv | awk -F'\t' '{print $2}'

# Force a specific format regardless of TTY detection
GPC_OUTPUT=csv gpc apps list

Use CSV/TSV when piping into tools like csvkit, mlr, or spreadsheet imports. Use JSON when you need nested structure or when piping into jq.

# Get version code from upload result
VERSION=$(gpc releases upload app.aab --track beta | jq -r '.data.versionCode')

# Check if vitals are OK
CRASH_RATE=$(gpc vitals crashes --output json | jq -r '.data.crashRate')

# Conditional promotion
if (( $(echo "$CRASH_RATE < 2.0" | bc -l) )); then
  gpc releases promote --from beta --to production --rollout 10
fi

7) Exit codes for CI logic

CodeMeaningCI Action
0SuccessContinue
1General errorFail job
2Usage error (bad arguments)Fix command
3Authentication errorCheck secrets
4API error (rate limit, permission)Retry or fix permissions
5Network errorRetry
6Threshold breach (vitals)Block promotion
10Plugin errorCheck plugin config
- name: Check vitals
  run: gpc vitals crashes --threshold 2.0
  continue-on-error: false  # Exit code 6 fails the job

8) Vitals-gated rollout pattern

- name: Upload to beta
  run: |
    gpc publish app.aab --track beta \
      --changes-not-sent-for-review \
      --mapping-type PROGUARD

- name: Wait for crash data
  run: sleep 3600  # Wait 1 hour for crash data

- name: Gate on vitals
  run: |
    gpc vitals crashes --threshold 2.0
    gpc vitals anr --threshold 0.47

- name: Promote to production
  run: gpc releases promote --from beta --to production --rollout 10

Wait for bundle processing before promoting (v0.9.69+)

After uploading a large AAB, bundle processing on Google's side can take 30–120 seconds. Use gpc bundles wait as an explicit gate instead of relying on the built-in Fibonacci polling inside gpc publish:

- name: Upload AAB
  run: |
    gpc releases upload app-release.aab \
      --track internal \
      --changes-not-sent-for-review

- name: Wait for bundle processing
  run: gpc bundles wait --version-code ${{ env.VERSION_CODE }}
  # Exits 0 when ACTIVE, non-zero on timeout or error.
  # Prevents INVALID_ARGUMENT errors when promoting before processing completes.

- name: Promote to beta
  run: gpc releases promote --from internal --to beta

This is especially useful in multi-job pipelines where upload and promote run in separate jobs.

Gate Play Store release notes on character budget (v0.9.62+)

      - name: Verify all locales fit Play Store 500-char budget
        run: |
          gpc changelog generate --target play-store \
            --locales auto \
            --app com.example.app \
            --strict
        # --strict exits 1 if any locale overflows; collects all overflows in one report.

Translate release notes on every tag (v0.9.63+)

      - name: Generate + translate Play Store release notes
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          # Or OPENAI_API_KEY / GOOGLE_GENERATIVE_AI_API_KEY / AI_GATEWAY_API_KEY
        run: |
          gpc changelog generate --target play-store \
            --locales auto \
            --app com.example.app \
            --ai \
            --strict \
            --format json > release-notes.json
        # --strict exits 1 if any locale fails to translate or overflows 500 chars.
        # --format json emits the `ai` block (provider, model, tokensIn, tokensOut,
        # plus runId + costUsd on the Gateway path) for log aggregation.

Write translated notes into a Play Store draft (v0.9.64+)

      - name: Write translated release notes into Play Store draft
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          gpc changelog generate --target play-store \
            --locales auto \
            --ai \
            --apply \
            --track production
        # --apply writes the result into the latest draft release on the track.
        # Requires a draft release to exist on the target track.
        # Exits with RELEASE_NO_DRAFT (code 1) if no draft found.

9) Dry-run for testing pipelines

Test your CI pipeline without making real changes:

- name: Test release pipeline (dry-run)
  run: |
    gpc releases upload app.aab --track beta --dry-run
    gpc releases promote --from beta --to production --rollout 10 --dry-run

9a) Handling rejected apps in CI

When Google Play rejects an app update, gpc releases status reports the rejection reason. Use --error-if-in-review to detect and handle in-review or rejected states in your pipeline:

- name: Check for rejection
  id: review-check
  run: gpc releases status --error-if-in-review
  continue-on-error: true

- name: Handle rejection
  if: steps.review-check.outcome == 'failure'
  run: |
    echo "Release was rejected or is still in review."
    echo "Check the Play Console for details."
    gpc releases status --output json | jq '.data.releases[] | select(.status == "rejected")'
    exit 1

The --error-if-in-review flag exits with code 4 if any release on the target track is in inReview or rejected status. Use this before uploading a new version to avoid EDIT_CONFLICT errors when a previous submission is still pending review.

10) Markdown output for GitHub step summaries

gpc releases status --output markdown >> $GITHUB_STEP_SUMMARY
gpc vitals overview --output markdown >> $GITHUB_STEP_SUMMARY

11) Supply chain security in CI

GPC's own CI uses 12 protection layers. When integrating GPC into your pipeline, follow these practices:

# Pin GPC version (don't rely on @latest in production)
- run: npm install -g @gpc-cli/cli@0.9.82 --ignore-scripts

# Or use the standalone binary (no npm supply chain risk)
- run: curl -fsSL https://raw.githubusercontent.com/yasserstudio/gpc/main/scripts/install.sh | bash

# Pin GitHub Actions to commit SHAs
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6

--ignore-scripts on all pnpm/npm install commands (v0.9.74+)

All CI pnpm install and npm install commands must use --ignore-scripts to block lifecycle-script execution by untrusted packages. GPC's own pnpm.onlyBuiltDependencies is set to ["turbo", "esbuild"] in package.json — only those two packages are permitted to run install scripts.

- name: Install dependencies
  run: pnpm install --frozen-lockfile --ignore-scripts

Lockfile integrity verification (v0.9.74+)

Verify pnpm-lock.yaml has not been tampered with before installing:

- name: Verify lockfile integrity
  run: |
    sha256sum pnpm-lock.yaml > /tmp/lockfile.sha256
    # Compare against the known-good SHA stored as a repo secret or artifact
    echo "${{ secrets.LOCKFILE_SHA256 }}  pnpm-lock.yaml" | sha256sum -c -

Step-scoped secrets (v0.9.74+)

Never set GPC_SERVICE_ACCOUNT at the job level. Always scope it to the specific step that needs it:

# WRONG — secret is available to every step in the job
jobs:
  release:
    env:
      GPC_SERVICE_ACCOUNT: ${{ secrets.PLAY_SERVICE_ACCOUNT }}

# CORRECT — secret only visible to the upload step
- name: Upload release
  env:
    GPC_SERVICE_ACCOUNT: ${{ secrets.PLAY_SERVICE_ACCOUNT }}
  run: gpc releases upload app-release.aab --track internal

Deep security scan (v0.9.74+)

GPC ships a pnpm security:deep script that runs deepsec scanning across all packages. Add it to your release pipeline:

- name: Deep security scan
  run: pnpm security:deep

workflow_dispatch trigger for manual re-runs (v0.9.74+)

Add workflow_dispatch: {} to every release workflow so engineers can re-trigger failed runs without creating a new tag:

on:
  push:
    tags: ['v*']
  workflow_dispatch: {}

For Socket.dev scanning on your own repo, add socket ci to your workflow:

- name: Socket Security Scan
  run: |
    npm install -g socket@latest --ignore-scripts
    socket ci --repo your-repo
  env:
    SOCKET_SECURITY_API_TOKEN: ${{ secrets.SOCKET_SECURITY_API_TOKEN }}

12) APK uploads

GPC auto-detects the file format and uses the correct API endpoint:

# AAB upload (recommended)
- run: gpc releases upload app-release.aab --track internal

# APK upload (auto-detected)
- run: gpc releases upload app-release.apk --track internal

# Draft release (not visible to users until explicitly released)
- run: gpc releases upload app-release.aab --track production --status draft

13) Retry and timeout configuration

env:
  GPC_MAX_RETRIES: '5'
  GPC_TIMEOUT: '60000'
  GPC_BASE_DELAY: '2000'
  GPC_MAX_DELAY: '120000'
  GPC_RATE_LIMIT: '50'

Use --retry-log to debug transient failures:

gpc releases upload app.aab --track beta --retry-log retries.log

Verification

  • CI job completes with exit code 0
  • gpc releases status (in subsequent step) confirms release is on expected track
  • GitHub Actions step summary shows release details
  • Vitals check exits 0 (below threshold) or 6 (above threshold) as expected

Failure modes / debugging

SymptomLikely CauseFix
AUTH_INVALID in CISecret not set or wrong formatVerify PLAY_SERVICE_ACCOUNT secret contains valid JSON
Permission deniedService account lacks Play Console accessGrant access in Play Console → Settings → API access
Timeout on uploadLarge AAB + slow CI networkIncrease GPC_TIMEOUT
Rate limitedToo many API callsIncrease GPC_BASE_DELAY, reduce parallelism
Exit code 6Vitals threshold breachedReview crash/ANR data, fix issues before promoting
EDIT_CONFLICTParallel runs editing same appSerialize release jobs or use job concurrency limits
IN_REVIEW or REJECTEDPrevious submission pending or rejectedUse --error-if-in-review before uploading; resolve rejection in Play Console first
Changes auto-submitted for reviewEdit committed without opt-out flagAdd --changes-not-sent-for-review to upload/push commands

Read:

  • references/troubleshooting.md

Related skills

  • gpc-setup: Initial authentication and configuration
  • gpc-release-flow: Release commands and rollout management
  • gpc-vitals-monitoring: Vitals metrics and review management
  • gpc-metadata-sync: Store listing automation

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.