npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

android-cicd

v1.0.4

Published

AI skill: automated Android CI/CD pipeline to Google Play — supports TWA, React Native, Flutter, and native Android

Readme

android-cicd

npm version License Node

AI skill: automated Android CI/CD pipeline to Google Play

Sets up a complete, multi-stage GitHub Actions pipeline to build a signed AAB and publish it to Google Play. Supports TWA (Bubblewrap), React Native, Flutter, and native Android.

Features

  • Auto-detects your Android framework from the project structure
  • Generates and manages your upload keystore (cross-platform: Windows + macOS/Linux)
  • Configures all 5 required GitHub Secrets automatically via gh CLI
  • Scaffolds a production-ready .github/workflows/publish-android.yml
  • Auto-increments versionCode on every push to main (commit with [skip ci])
  • Multi-stage pipeline: different tracks per branch/tag

Multi-Stage Pipeline

| Git event | Google Play track | |---|---| | Push to main | internal | | Tag v*-alpha (e.g. v1.2-alpha) | alpha | | Tag v*-beta (e.g. v1.2-beta) | beta | | Tag v* (e.g. v1.2.0) | production | | Manual workflow_dispatch | Selectable |

Quick Start

npx android-cicd

The interactive wizard will:

  1. Auto-detect your Android framework (TWA / React Native / Flutter / native)
  2. Generate an upload keystore — or use an existing one
  3. Set all required GitHub Secrets via gh CLI
  4. Scaffold .github/workflows/publish-android.yml

Prerequisites

  • Node.js ≥ 18
  • JDK 17 with keytool accessible (JAVA_HOME set, or installed via Eclipse Adoptium / Android Studio)
  • gh CLI installed and authenticated (gh auth login)
  • App already created in Google Play Consoleat least one manual AAB upload done
  • App enrolled in Play App Signing
  • Google Play Android Developer API enabled in Google Cloud Console
  • Service account JSON key downloaded (see Google Play Setup)

Supported Frameworks

| Framework | Detected by | Version file | |---|---|---| | TWA (Bubblewrap) | android-root-app/build.gradle or twa-manifest.json | android-root-app/build.gradle | | React Native | android/app/build.gradle + react-native in package.json | android/app/build.gradle | | Flutter | pubspec.yaml with flutter: | pubspec.yaml (+N build number) | | Native Android | app/build.gradle | app/build.gradle |

GitHub Secrets

The wizard sets these automatically. You can also set them manually in GitHub → Settings → Secrets and variables → Actions:

| Secret | Description | |---|---| | KEYSTORE_FILE | Base64-encoded upload keystore (.jks) | | KEYSTORE_PASSWORD | Keystore password | | KEY_ALIAS | Key alias (e.g. upload) | | KEY_PASSWORD | Key password | | GOOGLE_PLAY_SERVICE_ACCOUNT_JSON | Full JSON content of the service account key |

Google Play Setup

These steps cannot be automated — do them once before running the wizard:

1. Create a service account

  1. Google Cloud Console → your project → IAM & AdminService Accounts
  2. Create service account → name: github-play-publisherDone (no project roles needed)
  3. Click the service account → Keys tab → Add keyCreate new keyJSON → download the file

2. Enable the Play API

APIs & Services → search Google Play Android Developer APIEnable

3. Grant permissions in Play Console

Play ConsoleUsers and permissionsInvite new user

  • Email: [email protected]
  • Permissions (account level):
    • ✅ Release apps to testing tracks
    • ✅ Manage testing tracks and edit testers

Signing Configuration

TWA / React Native / Native Android

Add to your build.gradle (template at templates/gradle/signing.gradle):

android {
    signingConfigs {
        release {
            storeFile file("keystore.jks")
            storePassword System.getenv("KEYSTORE_PASSWORD")
            keyAlias System.getenv("KEY_ALIAS")
            keyPassword System.getenv("KEY_PASSWORD")
        }
    }
    buildTypes {
        release {
            minifyEnabled true
            signingConfig signingConfigs.release
        }
    }
}

Never set org.gradle.java.home in gradle.properties — it breaks Linux CI runners.

Flutter

Add to android/app/build.gradle (the CI workflow creates android/key.properties at build time):

def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}

android {
    signingConfigs {
        release {
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
            storePassword keystoreProperties['storePassword']
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}

Add android/key.properties to .gitignore.

Releasing to Production

# 1. Bump version manually (CI won't auto-bump on tags)
# TWA/Native/RN — edit build.gradle:  versionCode 8  versionName "1.2.0"
# Flutter — edit pubspec.yaml:        version: 1.2.0+8

git add .
git commit -m "chore: bump version to 1.2.0"

# 2. Tag and push
git tag v1.2.0
git push origin main --tags

Troubleshooting

| Error | Cause | Fix | |---|---|---| | Java home supplied is invalid | org.gradle.java.home in gradle.properties | Remove that line | | signed with the wrong key | Keystore in secret doesn't match Play's upload key | Update KEYSTORE_FILE secret | | The caller does not have permission | Service account missing permissions or API not enabled | Re-check Google Play Setup steps 2–3 | | Upload failed — wrong versionCode | versionCode not incremented before tagging | Increment manually before pushing the tag | | shallow update not allowed | Shallow checkout blocks the push-back | Workflow uses fetch-depth: 0 — verify the checkout step | | gh: command not found | gh CLI not installed | Install from https://cli.github.com | | keytool not found | JDK not installed or not on PATH | Set JAVA_HOME or install JDK 17 |

Recovering a Lost Upload Keystore

If enrolled in Play App Signing:

  1. Generate a new keystore: run npx android-cicd → choose "I already have a keystore: No"
  2. Export the PEM: keytool -export -rfc -keystore upload.jks -alias ALIAS -storepass PASS -file cert.pem
  3. Play Console → app → App integrityRequest upload key reset → "I forgot my password" → upload cert.pem
  4. Wait 1–2 business days
  5. Update the KEYSTORE_FILE secret by re-running npx android-cicd

Usage with AI Agents

This package ships a SKILL.md that AI coding agents (Claude, Cursor, Copilot, etc.) can read to gain full context for setting up and maintaining this pipeline. Point your agent at SKILL.md and ask it to run npx android-cicd in the target project.

License

MIT