Generated banner for Github Actions
Generated logo for Github Actions

Github Actions

CallstackOfficialPublished by Callstack

  • Skill
  • Tool integration
  • Software development
  • MIT
  • No issues found

From the author

GitHub Actions workflow patterns for React Native iOS simulator and Android emulator cloud builds with downloadable artifacts. Use when setting up CI build pipelines or downloading GitHub Actions artifacts via gh CLI and GitHub API.
— the description by Callstack

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a set of composite GitHub Actions and workflow patterns designed to streamline the CI process for React Native applications. It enables developers to automate the building of iOS simulator apps and Android emulator APKs directly within GitHub Actions. The patterns include logic for artifact naming, automated upload, and standardized retrieval methods using the GitHub CLI or REST API, facilitating easier testing and QA workflows.

What it does

  • Provides composite actions for building React Native iOS simulator apps.
  • Provides composite actions for building React Native Android emulator APKs.
  • Automates the upload of build artifacts to GitHub Actions storage.
  • Standardizes artifact naming conventions for easier identification.
  • Enables programmatic retrieval of build artifacts via GitHub CLI or REST API.
  • Supports dynamic identifier generation based on PR numbers or commit SHAs.

When to use it

  • When setting up CI/CD pipelines for React Native mobile projects.
  • When you need to provide downloadable simulator or emulator builds for QA teams.
  • When you want to replace manual local builds with automated cloud-based CI artifacts.
  • When you require stable artifact IDs for scripted download processes.

Advantages

  • Reduces manual effort by automating mobile build processes in the cloud.
  • Ensures consistent build environments for mobile artifacts.
  • Simplifies artifact management with standardized naming and retention.
  • Integrates seamlessly with existing GitHub Actions and CLI workflows.

Usage examples

“How do I build an Android emulator APK in my GitHub Actions workflow?”
You can use the provided Android composite action in your workflow file, which handles the Gradle build process and uploads the resulting APK as a named artifact.
“How can I download the latest iOS simulator build from my CI pipeline?”
After the build job completes, you can use the 'gh run download' command or the GitHub REST API to fetch the artifact using the stable ID generated by the composite action.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/callstackincubator/github-actions/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip github-actions.zip -d .agents/skills

Documentation by Callstack

GitHub Actions Build Artifacts

Overview

Reusable GitHub Actions patterns to build React Native apps for iOS simulators and Android emulators in the cloud, then publish artifacts retrievable via gh CLI or GitHub API.

When to Apply

Use this skill when:

  • Creating CI workflows that build React Native simulator/emulator artifacts.

  • Uploading iOS simulator and Android emulator installables from PRs or manual dispatch runs.

  • Replacing local-only mobile builds with downloadable CI artifacts.

  • Needing stable artifact IDs/names for scripted retrieval with gh or REST API.

Quick Reference

  1. Add composite actions from gha-ios-composite-action.md and gha-android-composite-action.md.

  2. Wire them into .github/workflows/mobile-build.yml from gha-workflow-and-downloads.md.

  3. Upload with actions/upload-artifact@v4 and capture artifact-id output.

  4. Download with gh run download or GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}/{archive_format}.

References

FileDescription
gha-ios-composite-action.mdComposite action.yml for iOS simulator .app.tar.gz builds and artifact upload
gha-android-composite-action.mdComposite action.yml for Android emulator .apk builds and artifact upload
gha-workflow-and-downloads.mdEnd-to-end workflow wiring plus gh and REST download commands

Problem -> Skill Mapping

ProblemStart With
Need CI iOS simulator .app.tar.gz artifactgha-ios-composite-action.md
Need CI Android emulator .apk artifactgha-android-composite-action.md
Need one workflow to trigger both platform jobsgha-workflow-and-downloads.md
Need scripted artifact downloadgha-workflow-and-downloads.md

Source Inspiration

Files

references/gha-ios-composite-action.md


title: iOS Simulator Composite Action (RN CLI) impact: HIGH tags: ios, simulator, github-actions, react-native, xcodebuild, artifact

Skill: iOS Simulator Composite Action (RN CLI)

Composite action template for building React Native iOS simulator apps in GitHub Actions and uploading .app.tar.gz artifacts.

Quick Config

  1. Create .github/actions/github-actions/ios-build/action.yml.

  2. Copy the template below.

  3. Set your app scheme and optional configuration.

  4. Use actions/upload-artifact@v4 outputs (artifact-id, artifact-url).

  5. Download later by ID (REST) or by run/name (gh run download).

When to Use

  • Need cloud iOS simulator build artifacts for QA or PR validation.

  • Need deterministic artifact naming and machine-readable IDs.

  • Need RN CLI project discovery without Rock (npx react-native config).

Prerequisites

  • macOS runner (macos-latest recommended).

  • Xcode scheme is known and buildable in CI.

  • JS dependencies installed before invoking the action.

Template (.github/actions/github-actions/ios-build/action.yml)

name: React Native iOS Simulator Build
description: Build React Native iOS simulator app in GitHub Actions and upload artifact

inputs:
  working-directory:
    description: Project root
    required: false
    default: "."
  scheme:
    description: Xcode scheme
    required: true
  configuration:
    description: Xcode configuration
    required: false
    default: Debug
  workspace-path:
    description: Optional path to .xcworkspace
    required: false
  project-path:
    description: Optional path to .xcodeproj
    required: false
  derived-data-path:
    description: DerivedData path relative to working-directory
    required: false
    default: build/ios/DerivedData
  artifact-prefix:
    description: Prefix for artifact naming
    required: false
    default: rn-ios-simulator
  custom-identifier:
    description: Optional stable identifier (PR number, channel, etc.)
    required: false
  artifact-retention-days:
    description: GitHub artifact retention
    required: false
    default: "7"

outputs:
  artifact-name:
    description: Uploaded artifact name
    value: ${{ steps.names.outputs.artifact_name }}
  artifact-id:
    description: Uploaded artifact id
    value: ${{ steps.upload.outputs.artifact-id }}
  artifact-url:
    description: Uploaded artifact URL
    value: ${{ steps.upload.outputs.artifact-url }}

runs:
  using: composite
  steps:
    - name: Validate inputs
      shell: bash
      run: |
        set -euo pipefail

        if [[ -n "${{ inputs.workspace-path }}" && -n "${{ inputs.project-path }}" ]]; then
          echo "Use workspace-path or project-path, not both"
          exit 1
        fi

    - name: Resolve iOS project settings
      id: resolve
      shell: bash
      working-directory: ${{ inputs.working-directory }}
      run: |
        set -euo pipefail

        CONFIG_JSON="$(npx react-native config)"
        IOS_SOURCE_DIR="$(printf '%s' "$CONFIG_JSON" | node -e "const fs=require('fs');const j=JSON.parse(fs.readFileSync(0,'utf8'));process.stdout.write(j.project?.ios?.sourceDir || 'ios')")"

        WORKSPACE="${{ inputs.workspace-path }}"
        PROJECT="${{ inputs.project-path }}"

        if [[ -z "$WORKSPACE" && -z "$PROJECT" ]]; then
          WORKSPACE="$(find "$IOS_SOURCE_DIR" -maxdepth 2 -name '*.xcworkspace' | head -n1 || true)"
          PROJECT="$(find "$IOS_SOURCE_DIR" -maxdepth 2 -name '*.xcodeproj' | head -n1 || true)"
        fi

        if [[ -n "$WORKSPACE" ]]; then
          CONTAINER_KIND="workspace"
          CONTAINER_PATH="$WORKSPACE"
        elif [[ -n "$PROJECT" ]]; then
          CONTAINER_KIND="project"
          CONTAINER_PATH="$PROJECT"
        else
          echo "Could not find .xcworkspace or .xcodeproj"
          exit 1
        fi

        IDENTIFIER="${{ inputs.custom-identifier }}"
        if [[ -z "$IDENTIFIER" ]]; then
          if [[ "${{ github.event_name }}" == "pull_request" ]]; then
            IDENTIFIER="pr-${{ github.event.pull_request.number }}"
          else
            IDENTIFIER="${GITHUB_SHA::7}"
          fi
        fi

        echo "container_kind=$CONTAINER_KIND" >> "$GITHUB_OUTPUT"
        echo "container_path=$CONTAINER_PATH" >> "$GITHUB_OUTPUT"
        echo "identifier=$IDENTIFIER" >> "$GITHUB_OUTPUT"

    - name: Build iOS simulator
      shell: bash
      working-directory: ${{ inputs.working-directory }}
      run: |
        set -euo pipefail

        if [[ "${{ steps.resolve.outputs.container_kind }}" == "workspace" ]]; then
          XCODE_CONTAINER=( -workspace "${{ steps.resolve.outputs.container_path }}" )
        else
          XCODE_CONTAINER=( -project "${{ steps.resolve.outputs.container_path }}" )
        fi

        xcodebuild \
          "${XCODE_CONTAINER[@]}" \
          -scheme "${{ inputs.scheme }}" \
          -configuration "${{ inputs.configuration }}" \
          -sdk iphonesimulator \
          -destination "generic/platform=iOS Simulator" \
          -derivedDataPath "${{ inputs.derived-data-path }}" \
          CODE_SIGNING_ALLOWED=NO \
          build

    - name: Package simulator app
      id: simulator
      shell: bash
      working-directory: ${{ inputs.working-directory }}
      run: |
        set -euo pipefail

        PRODUCTS_DIR="${{ inputs.derived-data-path }}/Build/Products"
        CONFIG_PRODUCTS_DIR="$PRODUCTS_DIR/${{ inputs.configuration }}-iphonesimulator"
        SEARCH_DIR="$PRODUCTS_DIR"
        if [[ -d "$CONFIG_PRODUCTS_DIR" ]]; then
          SEARCH_DIR="$CONFIG_PRODUCTS_DIR"
        fi

        # Prefer the app matching the scheme, then deterministic non-test fallbacks.
        APP_PATH="$(find "$SEARCH_DIR" -type d -name "${{ inputs.scheme }}.app" | sort | head -n1 || true)"
        if [[ -z "$APP_PATH" ]]; then
          APP_PATH="$(find "$SEARCH_DIR" -type d -name '*.app' \
            ! -name '*Tests*.app' \
            ! -name '*UITests*.app' \
            ! -name '*-Runner.app' \
            | sort | head -n1 || true)"
        fi
        if [[ -z "$APP_PATH" ]]; then
          APP_PATH="$(find "$SEARCH_DIR" -type d -name '*.app' | sort | head -n1 || true)"
        fi

        if [[ -z "$APP_PATH" ]]; then
          echo "No .app found in $SEARCH_DIR"
          exit 1
        fi

        mkdir -p build/ios
        APP_DIR="$(dirname "$APP_PATH")"
        APP_NAME="$(basename "$APP_PATH")"
        TARBALL="build/ios/${APP_NAME%.app}.app.tar.gz"
        tar -C "$APP_DIR" -czf "$TARBALL" "$APP_NAME"

        echo "artifact_path=$TARBALL" >> "$GITHUB_OUTPUT"

    - name: Build artifact name
      id: names
      shell: bash
      run: |
        set -euo pipefail

        CONFIG="$(echo "${{ inputs.configuration }}" | tr '[:upper:]' '[:lower:]')"
        NAME="${{ inputs.artifact-prefix }}-${CONFIG}-${{ steps.resolve.outputs.identifier }}"
        echo "artifact_name=$NAME" >> "$GITHUB_OUTPUT"

    - name: Upload artifact
      id: upload
      uses: actions/upload-artifact@v4
      with:
        name: ${{ steps.names.outputs.artifact_name }}
        path: ${{ steps.simulator.outputs.artifact_path }}
        if-no-files-found: error
        retention-days: ${{ inputs.artifact-retention-days }}

Common Pitfalls

  • Passing both workspace-path and project-path.

  • Uploading .app directly instead of tar.gz (permission loss risk).

  • Using non-macOS runner for iOS jobs.

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
Callstack
Publisher
Callstack (Official)
Source
callstackincubator/agent-skills · skills/github-actions · commit 59e9d17
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Callstack.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download github-actions.zip