Claude Code Plugins

Community-maintained marketplace

Feedback

android-workflow-production

@hitoshura25/claude-devtools
0
0

Generate GitHub Actions workflows for production deployment with staged rollout

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name android-workflow-production
description Generate GitHub Actions workflows for production deployment with staged rollout
category android
version 1.0.0
inputs [object Object]
outputs .github/workflows/deploy-production.yml, .github/workflows/manage-rollout.yml
verify yamllint .github/workflows/deploy-production.yml .github/workflows/manage-rollout.yml

Android Production Workflow

Generates GitHub Actions workflows for production deployment with staged rollouts and rollout management.

Prerequisites

  • Service account setup complete
  • Package name known
  • GitHub environment "production" created

Inputs

Input Required Default Description
package_name Yes - App package name

Process

Step 1: Verify Fastlane Setup

Ensure Fastlane is configured:

bundle exec fastlane lanes

Expected output should show deploy_production, increase_rollout, and halt_rollout lanes.

Step 2: Create Production Deployment Workflow

Create .github/workflows/deploy-production.yml:

name: Deploy to Production

on:
  workflow_dispatch:
    inputs:
      rollout_type:
        description: 'Rollout type'
        required: true
        type: choice
        options:
          - staged
          - full
        default: 'staged'
      rollout_percentage:
        description: 'Rollout percentage (only for staged: 0.05-1.0, e.g., 0.1 for 10%)'
        required: false
        default: '0.05'

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2

      - name: Set up JDK 17
        uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00  # v4.7.0
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Setup Gradle cache
        uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57  # v4.2.0
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
            .gradle/configuration-cache
          key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
          restore-keys: |
            gradle-${{ runner.os }}-

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v4

      - name: Run unit tests
        run: ./gradlew test

      - name: Upload test reports
        if: always()
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4.6.0
        with:
          name: test-reports
          path: app/build/reports/tests/
          retention-days: 7

  deploy:
    needs: test
    runs-on: ubuntu-latest
    environment: production

    steps:
      - name: Checkout code
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2
        with:
          fetch-depth: 0  # Full history for tags

      - name: Set up JDK 17
        uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00  # v4.7.0
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Setup Gradle cache
        uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57  # v4.2.0
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
            .gradle/configuration-cache
          key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
          restore-keys: |
            gradle-${{ runner.os }}-

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v4

      - name: Decode keystore
        run: |
          echo "${{ secrets.SIGNING_KEY_STORE_BASE64 }}" | base64 -d > app/release.jks
        env:
          SIGNING_KEY_STORE_BASE64: ${{ secrets.SIGNING_KEY_STORE_BASE64 }}

      - name: Build Release Bundle
        run: ./gradlew bundleRelease
        env:
          SIGNING_KEY_STORE_PATH: ${{ github.workspace }}/app/release.jks
          SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }}
          SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }}
          SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }}

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.2'
          bundler-cache: true

      - name: Create Service Account File
        run: echo "${{ secrets.SERVICE_ACCOUNT_JSON_PLAINTEXT }}" > service-account.json

      - name: Deploy with Fastlane (Full Rollout)
        if: github.event.inputs.rollout_type == 'full'
        env:
          SIGNING_KEY_STORE_PATH: ${{ github.workspace }}/app/release.jks
          SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }}
          SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }}
          SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }}
          PLAY_STORE_SERVICE_ACCOUNT: service-account.json
        run: bundle exec fastlane deploy_production rollout:1.0

      - name: Deploy with Fastlane (Staged Rollout)
        if: github.event.inputs.rollout_type == 'staged'
        env:
          SIGNING_KEY_STORE_PATH: ${{ github.workspace }}/app/release.jks
          SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }}
          SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }}
          SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }}
          PLAY_STORE_SERVICE_ACCOUNT: service-account.json
        run: bundle exec fastlane deploy_production rollout:${{ github.event.inputs.rollout_percentage }}

      - name: Cleanup Service Account
        if: always()
        run: rm -f service-account.json

      - name: Clean up keystore
        if: always()
        run: rm -f app/release.jks

      - name: Get latest tag
        id: get_tag
        run: |
          TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
          echo "tag=$TAG" >> $GITHUB_OUTPUT

      - name: Create GitHub Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          gh release create "${{ steps.get_tag.outputs.tag }}" \
            --title "Release ${{ steps.get_tag.outputs.tag }}" \
            --notes "Production release ${{ steps.get_tag.outputs.tag }}" \
            --latest \
            app/build/outputs/bundle/release/app-release.aab

      - name: Upload artifacts
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4.6.0
        with:
          name: production-release
          path: |
            app/build/outputs/bundle/release/app-release.aab
            app/build/outputs/mapping/release/mapping.txt
          retention-days: 365

Key features:

  • ✅ Uses Fastlane for deployment
  • ✅ Supports full and staged rollouts
  • ✅ Creates GitHub releases automatically
  • ✅ Pinned all actions to commit SHAs
  • ✅ Test job runs before deployment
  • ✅ Manual trigger only (no automatic tag deployment)

Step 3: Create Rollout Management Workflow

Note: Fastlane provides full support for rollout management through dedicated lanes.

Create .github/workflows/manage-rollout.yml:

name: Manage Production Rollout

on:
  workflow_dispatch:
    inputs:
      action:
        description: 'Rollout action'
        required: true
        type: choice
        options:
          - promote
          - halt
          - complete
      from_track:
        description: 'Source track (for promote action)'
        required: false
        type: choice
        options:
          - internal
          - alpha
          - beta
        default: 'beta'
      percentage:
        description: 'Rollout percentage (for promote: 0.05-1.0, e.g., 0.2 for 20%)'
        required: false
        default: '0.05'

jobs:
  manage-rollout:
    runs-on: ubuntu-latest
    environment: production

    steps:
      - name: Checkout code
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2

      - name: Set up JDK 17
        uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00  # v4.7.0
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.2'
          bundler-cache: true

      - name: Create Service Account File
        run: echo "${{ secrets.SERVICE_ACCOUNT_JSON_PLAINTEXT }}" > service-account.json

      - name: Increase Rollout
        if: github.event.inputs.action == 'promote'
        env:
          PLAY_STORE_SERVICE_ACCOUNT: service-account.json
        run: bundle exec fastlane increase_rollout rollout:${{ github.event.inputs.percentage }}

      - name: Complete Rollout (100%)
        if: github.event.inputs.action == 'complete'
        env:
          PLAY_STORE_SERVICE_ACCOUNT: service-account.json
        run: bundle exec fastlane increase_rollout rollout:1.0

      - name: Halt Rollout
        if: github.event.inputs.action == 'halt'
        env:
          PLAY_STORE_SERVICE_ACCOUNT: service-account.json
        run: bundle exec fastlane halt_rollout

      - name: Cleanup Service Account
        if: always()
        run: rm -f service-account.json

      - name: Notify result
        if: success()
        run: |
          echo "✅ Rollout action completed: ${{ github.event.inputs.action }}"
          if [ "${{ github.event.inputs.action }}" == "promote" ]; then
            echo "📊 Promoted from ${{ github.event.inputs.from_track }} to production"
            echo "📊 Rollout percentage: ${{ github.event.inputs.percentage }}"
          fi

Key features:

  • ✅ Uses Fastlane for rollout management
  • ✅ Supports increase, complete, and halt actions
  • ✅ Pinned all actions to commit SHAs

Step 3: Create Environment Setup Guide

Add to .github/workflows/README.md:

# GitHub Actions Workflows

## Production Environment Setup

**REQUIRED:** Create production environment for manual approval:

1. Go to: Repository → Settings → Environments
2. Click "New environment"
3. Name: `production`
4. Check "Required reviewers"
5. Add yourself and/or team members
6. Click "Save protection rules"

This ensures production deployments require manual approval.

## Workflows

### deploy-internal.yml
- **Trigger:** Push to main/develop
- **Track:** Internal testing
- **Approval:** None (automatic)

### deploy-production.yml
- **Trigger:** Tag push (v*) or manual
- **Track:** Production
- **Approval:** Required (via environment)
- **Rollout:** Staged (default 5%)

### manage-rollout.yml
- **Trigger:** Manual only
- **Actions:** increase, halt, resume, complete
- **Use:** Control production rollout percentage

## Usage

**Deploy to internal:**
```bash
git push origin main

Deploy to production:

git tag v1.0.0
git push origin v1.0.0
# Then approve in GitHub Actions tab

Increase rollout to 20%:

  1. Go to: Actions → Manage Production Rollout
  2. Click "Run workflow"
  3. Select action: "increase"
  4. Enter percentage: "20"
  5. Click "Run workflow"

Emergency halt:

  1. Go to: Actions → Manage Production Rollout
  2. Select action: "halt"
  3. Click "Run workflow"

## Verification

**MANDATORY:** Validate workflows:

```bash
# Validate YAML syntax
yamllint .github/workflows/deploy-production.yml
yamllint .github/workflows/manage-rollout.yml

# Verify package name
grep "packageName:" .github/workflows/*.yml

Outputs

Output Location Description
Production workflow .github/workflows/deploy-production.yml Production deployment
Rollout management .github/workflows/manage-rollout.yml Rollout control

Completion Criteria

  • deploy-production.yml exists and is valid
  • manage-rollout.yml exists and is valid
  • Package names are correct in both files
  • GitHub "production" environment created
  • Required reviewers configured