Skip to content

Github Action workflows

The template comes with over 10 GitHub Actions workflows that help you automate the process of checking, testing, releasing, and much more.

All those workflows are self-documented and contain all details directly inside the workflow file as comments. This approach makes it easier to understand what each workflow does and how to use it without having to go back and forth between the documentation and the workflow file.

This page lists all workflows and actions we use and adds more details on the approach we are using to make those workflows as simple as possible.

All files related to GitHub Actions are located in the .github/workflows and .github/actions folders.

Actions

You can think of actions as functions that are used by workflows to perform a specific task and allow you to reuse the same task in multiple workflows without duplicating the code which made them easier to maintain.

All actions are located in the .github/actions folder, and here is the complete list:

⚙️ Node setup and PNM install

.github/actions/setup-node-pnpm-install/action.yml
# 🔗 Links:
# Source file: https://github.com/rootstrap/react-native-template/blob/master/.github/actions/setup-node-pnpm-install/action.yml
# Composite actions docs: https://docs.github.com/en/actions/creating-actions/creating-a-composite-action
# ✍️ Description:
# This is a composite action, which means it can be used in other actions.
# It is used in almost all workflows to set up the environment and install dependencies.
# Updating the package manager or Node version here will be reflected in all workflows.
# 👀 Example usage:
# - name : 📦 Setup Node + PNPM + install deps
# uses: ./.github/actions/setup-node-pnpm-install
name: 'Setup Node + PNPM + Install Dependencies'
description: 'Setup Node + PNPM + Install Dependencies'
runs:
using: 'composite'
steps:
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false
- uses: actions/setup-node@v4
name: Install Node.js
with:
node-version: 20
cache: 'pnpm'
- name: 📦 Install Project Dependencies
run: pnpm install --frozen-lockfile
shell: bash

⚙️ Setup JDK && Generate APK

.github/actions/setup-jdk-generate-apk/action.yml
# 🔗 Links:
# Source file: https://github.com/rootstrap/react-native-template/blob/master/.github/actions/setup-jdk-generate-apk/action.yml
# Composite actions docs: https://docs.github.com/en/actions/creating-actions/creating-a-composite-action
# ✍️ Description:
# This is a composite action, which means it can be used in other actions.
# This action is used to set up the JDK environment and generate an Android APK for testing.
# This action accepts one input: `APP_ENV`, which is used to generate an APK for a specific environment (development, staging, production). We use staging by default.
# Before generating the APK, we run a pre-build script to generate the necessary native folders based on the APP_ENV.
# On success, the APK is generated at `./android/app/build/outputs/apk/release/app-release.apk`.
# 👀 Example usage:
# - name : 📦 Set Up JDK + Generate Test APK
# uses: ./.github/actions/setup-jdk-generate-apk
# with:
# APP_ENV: 'staging'
name: 'Setup JDK + GRADLE + Generate APK'
description: 'Setup JDK + GRADLE + Generate APK'
inputs:
APP_ENV:
description: 'APP_ENV (one of): development, staging, production'
required: true
default: 'staging'
runs:
using: 'composite'
steps:
- name: Set Up JDK
uses: actions/setup-java@v3
with:
distribution: 'zulu' # See 'Supported distributions' for available options
java-version: '11'
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Generate Test APK
run: |
pnpm prebuild:${{ inputs.APP_ENV }}
cd android
chmod +x ./gradlew
./gradlew assembleRelease --no-daemon
cd ..
shell: bash
env:
EXPO_NO_DOTENV: '1'
APP_ENV: ${{ inputs.APP_ENV }}
CI: 'true'

⚙️ EAS Build

.github/workflows/eas-build.yml
# 🔗 Links:
# Source file: https://github.com/rootstrap/react-native-template/blob/master/.github/workflows/eas-build.yml
# EAS Build docs: https://docs.expo.dev/eas-update/github-actions/
# ✍️ Description:
# This workflow is used to trigger a build on EAS.
# Can be triggered manually from the actions tab.
# This action accepts those inputs:
# `environment`, which is used to generate a build for a specific environment (development, staging, QA, production). We use staging by default.
# `android`, true by default, set to true if you don't want to trigger build for Android.
# `ios`, false by default, set to true if you want to trigger build for IOS.
# Before triggering the build, we run a pre-build script to generate the necessary native folders based on the APP_ENV.
# Based on the ANDROID and IOS inputs, we trigger the build for the corresponding platform with the corresponding flags.
# 🚨 GITHUB SECRETS REQUIRED:
# - EXPO_TOKEN: Expo token to authenticate with EAS
# - You can get it from https://expo.dev/settings/access-tokens
name: 'EAS Build (Android & IOS) (EAS)'
on:
workflow_dispatch:
inputs:
environment:
type: choice
description: 'Environment'
required: true
default: 'staging'
options:
- development
- staging
- qa
- production
android:
type: boolean
description: 'Build for Android'
required: true
default: true
ios:
type: boolean
description: 'Build for iOS'
required: true
default: true
jobs:
Build:
runs-on: ubuntu-latest
steps:
- name: Check for EXPO_TOKEN
run: |
if [ -z "${{ secrets.EXPO_TOKEN }}" ]; then
echo "You must provide an EXPO_TOKEN secret linked to this project's Expo account in this repo's secrets. Learn more: https://docs.expo.dev/eas-update/github-actions"
exit 1
fi
- name: 📦 Setup Expo and EAS
uses: expo/expo-github-action@v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}
- name: 📦 Checkout project repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: 📦 Setup Node + PNPM + install deps
uses: ./.github/actions/setup-node-pnpm-install
- name: ⚙️ Run Prebuild
run: pnpm prebuild:${{ inputs.environment }}
- name: 📱 Run Android Build
if: ${{ inputs.android == true }}
run: pnpm build:${{ inputs.environment }}:android --non-interactive --no-wait --message "Build ${{ inputs.environment }}"
- name: 📱 Run IOS Build
if: ${{ inputs.ios == true }}
run: pnpm build:${{ inputs.environment }}:ios --non-interactive --no-wait --message "Build ${{ inputs.environment }}"

Workflows

⚙️ Linting and formatting

.github/workflows/lint-ts.yml
# 🔗 Links:
# Source file: https://github.com/rootstrap/react-native-template/blob/master/.github/workflows/lint-ts.yml
# ✍️ Description:
# This action is used to run eslint checks
# Runs on any pull request, and also when pushing to main/master
# Based on the event type:
# - If it's a pull request, it will run eslint, then add the check to the PR as well as annotate the code with the errors and warnings.
# - If it's a push to main/master, it will run the type checking and fail if there are any errors.
# 🚨 GITHUB SECRETS REQUIRED: NONE
name: Lint TS (eslint, prettier)
on:
push:
branches: [main, master]
pull_request:
types: [opened, synchronize]
jobs:
lint:
name: Lint TS (eslint, prettier)
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: 📦 Checkout project repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: 📦 Setup Node + PNPM + install deps
uses: ./.github/actions/setup-node-pnpm-install
- name: 🏃‍♂️ Run ESLint PR
if: github.event_name == 'pull_request'
uses: reviewdog/action-eslint@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-review
eslint_flags: '. --ext .js,.jsx,.ts,.tsx'
- name: 🏃‍♂️ Run ESLint PR
if: github.event_name != 'pull_request'
run: pnpm run lint

⚙️ Type checking

.github/workflows/type-check.yml
# 🔗 Links:
# Source file: https://github.com/rootstrap/react-native-template/blob/master/.github/workflows/type-check.yml
# ✍️ Description:
# This action is used to run the type-check on the project.
# Runs on any pull request, and also when pushing to main/master
# Based on the event type:
# - If it's a pull request, it will run type checking, then add the check to the PR as well as annotate the code with the errors using reviewdog.
# - If it's a push to main/master, it will run the type checking and fail if there are any errors.
# 🚨 GITHUB SECRETS REQUIRED: NONE
name: Type Check (tsc)
on:
push:
branches: [main, master]
pull_request:
types: [opened, synchronize]
jobs:
type-check:
name: Type Check (tsc)
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: 📦 Checkout project repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: 📦 Setup Node + PNPM + install deps
uses: ./.github/actions/setup-node-pnpm-install
- name: 📦 Install Reviewdog
if: github.event_name == 'pull_request'
uses: reviewdog/action-setup@v1
- name: 🏃‍♂️ Run TypeScript PR # Reviewdog tsc errorformat: %f:%l:%c - error TS%n: %m
# We only need to add the reviewdog step if it's a pull request
if: github.event_name == 'pull_request'
run: |
pnpm type-check | reviewdog -name="tsc" -efm="%f(%l,%c): error TS%n: %m" -reporter="github-pr-review" -filter-mode="nofilter" -fail-on-error -tee
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name:
🏃‍♂️ Run TypeScript Commit
# If it's not a Pull Request then we just need to run the type-check
if: github.event_name != 'pull_request'
run: pnpm type-check

⚙️ Expo Doctor

.github/workflows/expo-doctor.yml
# 🔗 Links:
# Source file: https://github.com/rootstrap/react-native-template/blob/master/.github/workflows/expo-doctor.yml
# ✍️ Description:
# This workflow runs the expo doctor command to check if your project dependencies are aligned with the expo sdk version you are using.
# Can be triggered manually from the Actions tab in your project.
# Runs Also on pull requests and pushes to the main/master branch, but only if the `package.json` or `pnpm-lock.yaml` files have been changed.
# 🚨 GITHUB SECRETS REQUIRED: NONE
name: Expo Doctor (expo)
on:
push:
branches:
- main
- master
paths:
- 'package.json'
- 'pnpm-lock.yaml'
pull_request:
paths:
- 'package.json'
- 'pnpm-lock.yaml'
jobs:
doctor:
name: Expo Doctor (expo)
runs-on: ubuntu-latest
steps:
- name: 📦 Checkout project repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: 📦 Setup Node + PNPM + install deps
uses: ./.github/actions/setup-node-pnpm-install
- name: 🚑 Run Doctor Checks
run: rm -rf ios android && pnpm run doctor ## apprently the new update of expo will break if you already have ios and android folders in your project as they will show up a eas warning

⚙️ Compress Images

.github/workflows/compress-images.yml
# 🔗 Links:
# Source file: https://github.com/rootstrap/react-native-template/blob/master/.github/workflows/compress-images.yml
# ✍️ Description:
# This workflow is used to compress images in the repo.
# This workflow will trigger on a push to the "master" or "main" branch and only run when a new image is added or updated.
# If it's the case, it will compress those images and create a pull request with the compressed images.
# 🚨 GITHUB SECRETS REQUIRED: None
name: Compress images
on:
push:
branches:
- master
- main
paths:
- '**.jpg'
- '**.jpeg'
- '**.png'
- '**.webp'
workflow_dispatch:
jobs:
build:
name: calibreapp/image-actions
runs-on: ubuntu-latest
steps:
- name: Checkout Branch
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Compress Images
id: calibre
uses: calibreapp/image-actions@main
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
compressOnly: true
ignorePaths: 'node_modules/**,ios/**,android/**'
- name: Create Pull Request
if: steps.calibre.outputs.markdown != ''
uses: peter-evans/create-pull-request@v3
with:
title: Auto Compress Images
branch-suffix: timestamp
commit-message: Compress Images
body: ${{ steps.calibre.outputs.markdown }}

⚙️ Running Tests + Coverage Reports

.github/workflows/test.yml
# 🔗 Links:
# Source file: https://github.com/rootstrap/react-native-template/blob/master/.github/workflows/test.yml
# ✍️ Description:
# This action is used to run unit tests
# Runs on any pull request, and also when pushing to main/master
# Based on the event type:
# - If it's a pull request, it will run the tests and post a comment with coverage details.
# - If it's a push to main/master, it will run the tests and add the check to the commit.
# 🚨 GITHUB SECRETS REQUIRED: NONE
name: Tests (jest)
on:
push:
branches: [main, master]
pull_request:
types: [opened, synchronize]
jobs:
test:
name: Tests (jest)
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: 📦 Checkout project repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: 📦 Setup Node + PNPM + install deps
uses: ./.github/actions/setup-node-pnpm-install
- name: 🏃‍♂️ Run Tests
run: pnpm run test:ci
- name: Jest Coverage Comment
uses: MishaKav/jest-coverage-comment@main
if: (success() || failure()) && github.event_name == 'pull_request'
with:
coverage-summary-path: ./coverage/coverage-summary.json
summary-title: '💯 Test Coverage'
badge-title: Coverage
create-new-comment: false
junitxml-title: 😎 Tests Results
junitxml-path: ./coverage/jest-junit.xml
coverage-title: 👀 Tests Details
coverage-path: ./coverage/coverage.txt
report-only-changed-files: true

⚙️ New App Version

.github/workflows/new-template-version.yml
# 🔗 Links:
# Source file: https://github.com/rootstrap/react-native-template/blob/master/.github/workflows/lint-ts.yml
# Starter releasing process: https://rootstrap.github.io/react-native-template/ci-cd/app-releasing-process/
# ✍️ Description:
# This workflow is used to create a new version of the template and push a new tag to the repo.
# As this workflow will push code to the repo, we set up GitHub Bot as a Git user.
# This Workflow need to be triggered manually from the Actions tab in the repo.
# 1. Choose your release type (patch, minor, major)
# 2. The workflow will run the np-release script which runs the following steps:
# - Bump the version in package.json based on the release type using np
# - Run the prebuild of the app to align the package.json version with the native code
# - Create a new tag with the new version
# - Push the new tag to the repo
#
# 🚨 GITHUB SECRETS REQUIRED:
# - NEW_TEMPLATE_VERSION_PAT: A fine-grained Personal Access Token.
# This token is used to commit, push and create a new release in the template repository.
# You can generate one from here: https://github.com/settings/tokens?type=beta
# Set the Repository access to "Only select repositories" and select the template repository.
# Set the following Repo permissions:
# - Contents: Read & write (to commit, push and create a new release)
# - Metadata: Read-only (mandatory by GitHub)
# - Actions: Read and write (to allow triggering other workflows, like docs deployment)
# Make sure to add it to the repo secrets with the name NEW_TEMPLATE_VERSION_PAT:
# - Go to Repository Settings > Secrets and variables > Actions > New repository secret
# - Name: NEW_TEMPLATE_VERSION_PAT
# - Value: The Personal Access Token you created
name: New Template Version
on:
workflow_dispatch:
inputs:
release-type:
type: choice
description: 'Release type (one of): patch, minor, major'
required: true
default: 'patch'
options:
- patch
- minor
- major
jobs:
release:
name: Create New Version and push new tag
runs-on: ubuntu-latest
environment:
name: template
url: https://github.com/rootstrap/react-native-template/releases/tag/v${{ env.NEW_VERSION }}
permissions:
contents: write
steps:
- name: Check if Personal Access Token exists
env:
PAT: ${{ secrets.NEW_TEMPLATE_VERSION_PAT }}
if: env.PAT == ''
run: |
echo "NEW_TEMPLATE_VERSION_PAT secret not found. Please create a fine-grained Personal Access Token following the instructions in the workflow file."
exit 1
- name: 📦 Checkout project repo
uses: actions/checkout@v3
with:
fetch-depth: 0
token: ${{ secrets.NEW_TEMPLATE_VERSION_PAT }}
- name: 📝 Git User Setup
run: |
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
- name: 📦 Setup Node + PNPM + install deps
uses: ./.github/actions/setup-node-pnpm-install
- name: 🏃‍♂️ Run Template release
run: |
pnpm app-release ${{ github.event.inputs.release-type }}
- name: 📝 Get new package version
run: |
echo "NEW_VERSION=$(awk -F'"' '/"version": ".+"/{ print $4; exit; }' package.json)" >> $GITHUB_ENV
- name: 🏃‍♂️Create A Github Release
uses: ncipollo/release-action@v1
with:
tag: v${{ env.NEW_VERSION }}
generateReleaseNotes: true
draft: false
token: ${{ secrets.NEW_TEMPLATE_VERSION_PAT }}

⚙️ E2E Test for Android

.github/workflows/e2e-android.yml
# 🔗 Links:
# Source file: https://github.com/rootstrap/react-native-template/blob/master/.github/workflows/e2e-android.yml
# End-to-end testing: https://rootstrap.github.io/react-native-template/testing/end-to-end-testing/
# ✍️ Description:
# This workflow is used to run end-to-end tests on Android using Maestro.
# As a first step, it will generate a test APK using the Gradle build and then upload it as an artifact.
# A new job will be started to run the tests using the test APK generated in the previous job.
# To test the app, we set up an Android emulator using the `reactivecircus/android-emulator-runner` action. This runner requires macOS as the operating system for the runner.
# This workflow will be triggered on pull requests (PRs) with the label "android-test-github" or can be manually triggered from the Actions tab.
#
# 🚨 GITHUB SECRETS REQUIRED: None
name: E2E Tests Android (Maestro + Github Action)
on:
workflow_dispatch:
pull_request:
branches: [main, master]
jobs:
generate-test-apk:
if: github.event_name != 'pull_request' || ( github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'android-test-github'))
name: Generate Test APK (Gradle)
runs-on: ubuntu-latest
steps:
- name: 📦 Checkout project repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: 📦 Setup Node + PNPM + install deps
uses: ./.github/actions/setup-node-pnpm-install
- name: 📦 Set Up JDK + Generate Test APK
uses: ./.github/actions/setup-jdk-generate-apk
with:
APP_ENV: staging
- name: Upload Test APK
uses: actions/upload-artifact@v3
with:
name: test-apk
path: ./android/app/build/outputs/apk/release/app-release.apk
test-android:
name: Run Android E2E Tests (Maestro + Github Action)
needs: generate-test-apk
runs-on: macOS-latest
steps:
- name: 📦 Checkout project repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: 📦 Install Maestro
run: npm run install-maestro ## We use npm because we don't need to install deps again
- name: Download Test APK
uses: actions/download-artifact@v3
with:
name: test-apk
path: ${{ github.workspace }}
- name: Gradle cache
uses: gradle/gradle-build-action@v2
- name: AVD cache
uses: actions/cache@v3
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-cache
- name: create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 29
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: false
cores: 2
ram-size: 4096M
profile: Nexus 6
script: echo "Generated AVD snapshot for caching."
- name: Run tests with Maestro
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 29
force-avd-creation: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: false
cores: 2
ram-size: 4096M
profile: Nexus 6
script: |
adb install "${{ github.workspace }}/app-release.apk"
$HOME/.maestro/bin/maestro test .maestro/ --env=APP_ID=com.obytes.staging --format junit
- name: Upload artifacts
if: always()
uses: actions/upload-artifact@v3
with:
name: e2e-test-logs
path: ~/.maestro/tests/**/*
- name: Store tests result
uses: actions/upload-artifact@v3
with:
name: e2e_android_report
path: |
report.xml

⚙️ E2E Test for Android using Maestro Cloud

.github/workflows/e2e-android-maestro.yml
# 🔗 Links:
# Source file: https://github.com/rootstrap/react-native-template/blob/master/.github/workflows/e2e-android.yml
# End-to-end testing: https://rootstrap.github.io/react-native-template/testing/end-to-end-testing/
# ✍️ Description:
# This workflow is used to run end-to-end tests on Android using Maestro Cloud.
# As a first step, it will generate a test APK using the Gradle build and then trigger Maestro Cloud to run the tests on the generated APK.
# This workflow will be triggered on pull requests (PRs) with the label "android-test-maestro-cloud" or can be manually triggered from the Actions tab.
# 🚨 GITHUB SECRETS REQUIRED:
# MAESTRO_CLOUD_API_KEY: API key for Maestro Cloud. You can get it from https://cloud.mobile.dev/ci-integration/github-actions#add-your-api-key-secret
name: E2E Tests Android (Maestro Cloud)
on:
workflow_dispatch:
pull_request:
branches: [main, master]
jobs:
generate-and-test-apk:
if: github.event_name != 'pull_request' || ( github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'android-test-maestro-cloud'))
name: Generate and Test Test APK (Maestro Cloud)
runs-on: ubuntu-latest
steps:
- name: 📦 Checkout project repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: 📦 Setup Node + PNPM + install deps
uses: ./.github/actions/setup-node-pnpm-install
- name: 📦 Set Up JDK + Generate Test APK
uses: ./.github/actions/setup-jdk-generate-apk
with:
APP_ENV: staging
- name: Upload Test APK
uses: actions/upload-artifact@v3
with:
name: test-apk
path: ./android/app/build/outputs/apk/release/app-release.apk
- name: 📱 Run E2E Tests with Maestro Cloud
uses: mobile-dev-inc/action-maestro-cloud@v1.4.1
with:
api-key: ${{ secrets.MAESTRO_CLOUD_API_KEY }}
app-file: ./android/app/build/outputs/apk/release/app-release.apk
env: |
APP_ID=com.obytes.staging

⚙️ E2E Test for Android using EAS Build

.github/workflows/e2e-android-eas-build.yml
# 🔗 Links:
# Source file: https://github.com/rootstrap/react-native-template/blob/master/.github/workflows/e2e-android-eas-build.yml
# End-to-end testing: https://rootstrap.github.io/react-native-template/testing/end-to-end-testing/
# ✍️ Description:
# This workflow is used to run end-to-end tests for EAS build on Android.
# It uses Maestro Cloud to run tests on Android emulator.
# It downloads the APK from EAS build and triggers the tests on Maestro Cloud with the downloaded APK.
# 🚨 GITHUB SECRETS REQUIRED:
# MAESTRO_CLOUD_API_KEY: API key for Maestro Cloud. You can get it from https://cloud.mobile.dev/ci-integration/github-actions#add-your-api-key-secret
name: E2E Tests EAS Build Android (Maestro + Github Action)
on:
workflow_dispatch:
inputs:
apk-url:
type: string
description: 'EAS APK URL'
required: true
default: ''
jobs:
download-eas-apk:
if: github.event_name != 'pull_request' && github.event.inputs.apk-url != ''
name: Download Test APK From EAS Url (wget)
runs-on: ubuntu-latest
steps:
- name: 📦 Download EAS APK
run: wget ${{ github.event.inputs.apk-url }} -O ./app-release.apk
- name: Upload Test APK
uses: actions/upload-artifact@v3
with:
name: test-apk
path: ./app-release.apk
test-android:
name: E2E Tests EAS Build Android (Maestro + Github Action)
needs: download-eas-apk
runs-on: macOS-latest
steps:
- name: 📦 Checkout project repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: 📦 Install Maestro
run: npm run install-maestro ## We use npm because we don't need to install deps again
- name: Download Test APK
uses: actions/download-artifact@v3
with:
name: test-apk
path: ${{ github.workspace }}
- name: Gradle cache
uses: gradle/gradle-build-action@v2
- name: AVD cache
uses: actions/cache@v3
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-cache
- name: create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 29
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: false
cores: 2
ram-size: 4096M
profile: Nexus 6
script: echo "Generated AVD snapshot for caching."
- name: Run tests with Maestro
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 29
force-avd-creation: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: false
cores: 2
ram-size: 4096M
profile: Nexus 6
script: |
adb install "${{ github.workspace }}/app-release.apk"
$HOME/.maestro/bin/maestro test .maestro/ --env=APP_ID=com.obytes.staging --format junit
- name: Upload artifacts
if: always()
uses: actions/upload-artifact@v3
with:
name: e2e-test-logs
path: ~/.maestro/tests/**/*
- name: Store tests result
uses: actions/upload-artifact@v3
with:
name: e2e_android_report
path: |
report.xml

⚙️ Sync with template

.github/project-workflows/sync-with-template.yml
# 🔗 Links:
# Source file: https://github.com/rootstrap/react-native-template/blob/master/.github/project-workflows/sync-with-template.yml
# ✍️ Description:
# This workflow is used to keep the project up to date with the latest version of the template.
# 🚨 GITHUB SECRETS REQUIRED:
# - UPDATE_FROM_TEMPLATE_PAT: A fine-grained Personal Access Token.
# This token is used to commit and push to the project repository.
# You can generate one from here: https://github.com/settings/tokens?type=beta
# Set the Repository access to "Only select repositories" and select the project repository.
# Set the following Repo permissions:
# - Contents: Read & write (to commit and push the update branch to the project repository)
# - Metadata: Read-only (mandatory by GitHub)
# - Workflows: Read and write (to create, update and delete workflows in the project repository)
# Make sure to add it to the repo secrets with the name UPDATE_FROM_TEMPLATE_PAT:
# - Go to Repository Settings > Secrets and variables > Actions > New repository secret
# - Name: UPDATE_FROM_TEMPLATE_PAT
# - Value: The Personal Access Token you created
# ℹ️ Environment variables:
# - TEMPLATE_REPOSITORY: Repository to sync with
# - DIFF_EXCLUDED_ROUTES: List of files or directories to exclude from the diff.
# Any changes in these files or directories will be ignored
# and won't be incorporated to the Pull Request.
name: 🔄 Sync with template
on:
schedule:
- cron: '0 12 * * 1-5' # At 12:00 UTC on every day-of-week from Monday through Friday
workflow_dispatch:
inputs:
template-version:
type: string
description: 'Template release version to sync with (e.g. v1.0.0). Leave empty to sync with the latest release.'
required: false
default: ''
env:
TEMPLATE_REPOSITORY: rootstrap/react-native-template
DIFF_EXCLUDED_ROUTES: |
cli
docs
ios
android
.github/workflows/deploy-docs.yml
.github/workflows/new-template-version.yml
.github/workflows/upstream-to-pr.yml
.github/workflows/sync-with-upstream.yml
README-project.md
jobs:
sync:
runs-on: ubuntu-latest
permissions:
actions: write
contents: read
pull-requests: write
steps:
- name: Check if Personal Access Token exists
env:
PAT: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }}
if: env.PAT == ''
run: |
echo "UPDATE_FROM_TEMPLATE_PAT secret not found. Please create a fine-grained Personal Access Token following the instructions in the workflow file."
exit 1
- name: Checkout project repository
uses: actions/checkout@v3
with:
fetch-depth: 0
path: project
token: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }}
- name: Get template version used in project from package.json
run: |
echo "PROJECT_TEMPLATE_VERSION=v$(jq -r 'if has("rsMetadata") then .rsMetadata.templateVersion else .osMetadata.initVersion end' project/package.json | sed 's/^.*@//')" >> $GITHUB_ENV
- name: Set template version to sync with
run: |
if [ -z "${{ inputs.template-version }}" ]; then
TEMPLATE_UPDATE_VERSION=$(curl -s https://api.github.com/repos/${{ env.TEMPLATE_REPOSITORY }}/releases/latest | jq '.tag_name' | sed 's/\"//g')
else
TEMPLATE_UPDATE_VERSION=${{ inputs.template-version }}
fi
echo "TEMPLATE_UPDATE_VERSION=$TEMPLATE_UPDATE_VERSION" >> $GITHUB_ENV
- name: Check if the project is up to date
run: |
if [[ $TEMPLATE_UPDATE_VERSION == $PROJECT_TEMPLATE_VERSION ]]; then
echo "Template is up to date"
cd project
gh run cancel ${{ github.run_id }}
gh run watch ${{ github.run_id }}
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check if branch already exists
run: |
cd project
git fetch origin
BRANCH_NAME=update-template-${{ env.TEMPLATE_UPDATE_VERSION }}
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
git branch -r | grep -q "origin/$BRANCH_NAME" && echo "BRANCH_EXISTS=true" >> $GITHUB_ENV || echo "BRANCH_EXISTS=false" >> $GITHUB_ENV
- name: Check if PR already exists
run: |
cd project
prs=$(gh pr list \
--head "$BRANCH_NAME" \
--json title \
--jq 'length')
if ((prs > 0)); then
echo "PR_EXISTS=true" >> $GITHUB_ENV
else
echo "PR_EXISTS=false" >> $GITHUB_ENV
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install dependencies
if: ${{ env.BRANCH_EXISTS == 'false' }}
run: |
sudo apt install wiggle
- name: Checkout update release of template
if: ${{ env.BRANCH_EXISTS == 'false' }}
uses: actions/checkout@v3
with:
repository: ${{ env.TEMPLATE_REPOSITORY }}
ref: ${{ env.TEMPLATE_UPDATE_VERSION }}
fetch-depth: 0
path: react-native-template
- name: Get diff between latest release and used release
if: ${{ env.BRANCH_EXISTS == 'false' }}
run: |
EXCLUDED_ROUTES=""
for route in $DIFF_EXCLUDED_ROUTES; do
EXCLUDED_ROUTES="$EXCLUDED_ROUTES ':(exclude)$route'"
done
cd react-native-template
git diff ${{ env.PROJECT_TEMPLATE_VERSION }} -- . $(echo $EXCLUDED_ROUTES | xargs) > ../update.patch
- name: Update template version in package.json
if: ${{ env.BRANCH_EXISTS == 'false' }}
run: |
cd project
jq 'del(.osMetadata)' package.json > tmp.json && mv tmp.json package.json
PLAIN_VERSION=${TEMPLATE_UPDATE_VERSION#v}
jq --arg version $PLAIN_VERSION '.rsMetadata.templateVersion = $version' package.json > tmp.json && mv tmp.json package.json
- name: Apply diff to project repository
if: ${{ env.BRANCH_EXISTS == 'false' }}
run: |
cd project
git apply --reject ../update.patch
continue-on-error: true
- name: Solve conflicts with wiggle
if: ${{ env.BRANCH_EXISTS == 'false' }}
run: |
cd project
find . -iname '*.rej' -exec sh -c 'printf "%s\n" "${0%.*}"' {} ';' | xargs -I _ wiggle --replace --merge _ _.rej
continue-on-error: true
- name: Remove wiggle's backup and .rej files
if: ${{ env.BRANCH_EXISTS == 'false' }}
run: |
cd project
find . -not -path './.git/*' -type f -name '*.porig' -delete
find . -not -path './.git/*' -type f -name '*.rej' -delete
- name: Commit and push changes to the update branch
if: ${{ env.BRANCH_EXISTS == 'false' }}
run: |
cd project
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
git checkout -b ${{ env.BRANCH_NAME }}
git add .
git commit -m "chore: update template to ${{ env.TEMPLATE_UPDATE_VERSION }}"
git push origin ${{ env.BRANCH_NAME }}
echo "BRANCH_EXISTS=true" >> $GITHUB_ENV
- name: 🎉 Create PR with changes
if: ${{ env.BRANCH_EXISTS == 'true' && env.PR_EXISTS == 'false' }}
run: |
cd project
gh pr create --title "chore: update template to ${{ env.TEMPLATE_UPDATE_VERSION }}" --body "Integrating latest changes from [rootstrap/react-native-template@${{ env.TEMPLATE_UPDATE_VERSION }}](https://github.com/rootstrap/react-native-template/releases/tag/${{ env.TEMPLATE_UPDATE_VERSION }})" --head ${{ env.BRANCH_NAME }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}