Skip to content

Commit 46a1412

Browse files
committed
Add example workflow configurations for CI/CD and cloud storage integration
1 parent bcbf123 commit 46a1412

File tree

4 files changed

+856
-0
lines changed

4 files changed

+856
-0
lines changed

examples/README.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Example Workflows
2+
3+
This directory contains example workflow configurations for different deployment and storage options. These examples can be used as templates for your own projects.
4+
5+
## Available Examples
6+
7+
### 1. Generalized Workflow
8+
9+
**File:** `generalized-workflow.yml`
10+
11+
The primary workflow template that works with any cloud storage provider. This is the most flexible and recommended starting point.
12+
13+
**Key features:**
14+
15+
- Cloud-agnostic storage integration
16+
- Comprehensive build pipeline
17+
- Skip CI functionality
18+
- Optimized caching
19+
- Path-ignore rules for documentation updates
20+
21+
### 2. GitHub Releases Workflow
22+
23+
**File:** `github-release-workflow.yml`
24+
25+
This workflow builds your React Native / Expo app and creates GitHub Releases with:
26+
27+
- Draft release for manual review before publishing
28+
- Automatic changelog generation from commit messages
29+
- Versioning based on app.json and build date
30+
- All build artifacts (APK, AAB) attached to the release
31+
32+
**Key features:**
33+
34+
- No external storage dependencies
35+
- Version tracking through GitHub's interface
36+
- Easy distribution via GitHub Release URLs
37+
- Automatic changelog generation
38+
39+
### 3. Zoho Drive Integration
40+
41+
**File:** `zoho-drive-workflow.yml`
42+
43+
This workflow builds your app and uploads the artifacts to Zoho Drive:
44+
45+
- Organized folder structure by version and build date
46+
- Direct uploads via rclone
47+
- Secure token-based authentication
48+
- Support for all build variants (dev, prod-apk, prod-aab)
49+
50+
**Key features:**
51+
52+
- Cloud storage integration
53+
- Version-based organization
54+
- Secure configuration
55+
- Team sharing capabilities
56+
57+
## How to Use These Examples
58+
59+
1. Choose the example that best fits your needs
60+
2. Copy the workflow file to `.github/workflows/` in your project
61+
3. Configure the necessary secrets in your GitHub repository settings
62+
4. Customize the workflow as needed for your specific project
63+
64+
## Required Secrets
65+
66+
### For Generalized Workflow
67+
68+
- `EXPO_TOKEN`: Your Expo account token
69+
- `CLOUD_STORAGE_TYPE`: Your cloud storage provider type (e.g., "zoho", "drive")
70+
- `CLOUD_STORAGE_TOKEN`: Authentication token for your cloud storage
71+
- `CLOUD_STORAGE_ROOT_ID`: Root folder ID in your cloud storage
72+
73+
### For GitHub Releases Workflow
74+
75+
- `EXPO_TOKEN`: Your Expo account token
76+
77+
### For Zoho Drive Integration
78+
79+
- `EXPO_TOKEN`: Your Expo account token
80+
- `RCLONE_CONFIG_ZOHODRIVE_TYPE`: Set to "zoho" for Zoho Drive
81+
- `RCLONE_CONFIG_ZOHODRIVE_TOKEN`: Authentication token for Zoho Drive
82+
- `RCLONE_CONFIG_ZOHODRIVE_DRIVE_ID`: Root folder ID in Zoho Drive
83+
84+
## Customization
85+
86+
These workflows can be further customized for your specific needs:
87+
88+
- Add iOS build support
89+
- Integrate with testing frameworks
90+
- Add notification systems (Slack, Discord, email)
91+
- Configure automatic app store submissions
92+
93+
## Contributor
94+
95+
Created by [Tanay Kedia](https://github.com/TanayK07)

examples/generalized-workflow.yml

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
name: React Native CI/CD
2+
3+
on:
4+
push:
5+
branches: [main, master, develop]
6+
paths-ignore:
7+
- "**.md"
8+
- "LICENSE"
9+
- ".github/ISSUE_TEMPLATE/**"
10+
- ".github/PULL_REQUEST_TEMPLATE.md"
11+
- "docs/**"
12+
pull_request:
13+
branches: [main, master]
14+
paths-ignore:
15+
- "**.md"
16+
- "LICENSE"
17+
- ".github/ISSUE_TEMPLATE/**"
18+
- ".github/PULL_REQUEST_TEMPLATE.md"
19+
- "docs/**"
20+
workflow_dispatch:
21+
inputs:
22+
buildType:
23+
type: choice
24+
description: "Build type to run"
25+
options:
26+
- all
27+
- dev
28+
- prod-apk
29+
- prod-aab
30+
31+
env:
32+
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
33+
CLOUD_STORAGE_TYPE: ${{ secrets.CLOUD_STORAGE_TYPE }}
34+
CLOUD_STORAGE_TOKEN: ${{ secrets.CLOUD_STORAGE_TOKEN }}
35+
CLOUD_STORAGE_ROOT_ID: ${{ secrets.CLOUD_STORAGE_ROOT_ID }}
36+
# Keeping legacy provider for older Node.js versions
37+
NODE_OPTIONS: --openssl-legacy-provider
38+
39+
jobs:
40+
# Skip CI job if commit message contains [skip ci]
41+
check-skip:
42+
runs-on: ubuntu-latest
43+
if: "!contains(github.event.head_commit.message, '[skip ci]')"
44+
steps:
45+
- name: Skip CI check
46+
run: echo "Proceeding with workflow"
47+
48+
test:
49+
needs: check-skip
50+
runs-on: ubuntu-latest
51+
steps:
52+
- name: 🏗 Checkout repository
53+
uses: actions/checkout@v4
54+
55+
- name: 🏗 Setup Node.js
56+
uses: actions/setup-node@v4
57+
with:
58+
node-version: "20"
59+
cache: "yarn"
60+
61+
- name: 📦 Install dependencies
62+
run: yarn install
63+
64+
- name: 🧪 Run TypeScript check
65+
run: yarn tsc
66+
67+
- name: 🧹 Run ESLint
68+
run: yarn lint
69+
70+
- name: 🎨 Run Prettier check
71+
run: yarn format:check
72+
73+
build-and-deploy:
74+
needs: test
75+
if: (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')) || github.event_name == 'workflow_dispatch'
76+
runs-on: ubuntu-latest
77+
steps:
78+
- name: 🏗 Checkout repository
79+
uses: actions/checkout@v4
80+
81+
- name: 🏗 Setup Node.js
82+
uses: actions/setup-node@v4
83+
with:
84+
node-version: "20"
85+
cache: "yarn"
86+
87+
- name: 📦 Install dependencies
88+
run: |
89+
yarn install
90+
yarn global add eas-cli@latest
91+
92+
- name: 📱 Setup EAS build cache
93+
uses: actions/cache@v3
94+
with:
95+
path: ~/.eas-build-local
96+
key: ${{ runner.os }}-eas-build-local-${{ hashFiles('**/package.json') }}
97+
restore-keys: |
98+
${{ runner.os }}-eas-build-local-
99+
100+
- name: 🔄 Verify EAS CLI installation
101+
run: |
102+
echo "EAS CLI version:"
103+
eas --version
104+
105+
- name: 📋 Fix package.json main entry
106+
run: |
107+
# Check if jq is installed, if not install it
108+
if ! command -v jq &> /dev/null; then
109+
echo "Installing jq..."
110+
sudo apt-get update && sudo apt-get install -y jq
111+
fi
112+
113+
# Fix the main entry in package.json
114+
if [ -f ./package.json ]; then
115+
# Create a backup
116+
cp package.json package.json.bak
117+
# Update the package.json
118+
jq '.main = "node_modules/expo/AppEntry.js"' package.json > package.json.tmp && mv package.json.tmp package.json
119+
echo "Updated package.json main entry"
120+
cat package.json | grep "main"
121+
else
122+
echo "package.json not found"
123+
exit 1
124+
fi
125+
126+
- name: 📋 Update metro.config.js for SVG support
127+
run: |
128+
if [ -f ./metro.config.js ]; then
129+
echo "Creating backup of metro.config.js"
130+
cp ./metro.config.js ./metro.config.js.backup
131+
echo "Updating metro.config.js to CommonJS format"
132+
cat > ./metro.config.js << 'EOFMARKER'
133+
/* eslint-disable @typescript-eslint/no-var-requires */
134+
const { getDefaultConfig } = require('expo/metro-config');
135+
136+
const config = getDefaultConfig(__dirname);
137+
138+
const { transformer, resolver } = config;
139+
140+
config.transformer = {
141+
...transformer,
142+
babelTransformerPath: require.resolve('react-native-svg-transformer/expo'),
143+
};
144+
145+
config.resolver = {
146+
...resolver,
147+
assetExts: resolver.assetExts.filter(ext => ext !== 'svg'),
148+
sourceExts: [...resolver.sourceExts, 'svg'],
149+
};
150+
151+
module.exports = config;
152+
EOFMARKER
153+
echo "metro.config.js updated to CommonJS format"
154+
else
155+
echo "metro.config.js not found"
156+
fi
157+
158+
- name: 📱 Build Development APK
159+
if: github.event.inputs.buildType == 'all' || github.event.inputs.buildType == 'dev' || github.event_name == 'push'
160+
run: |
161+
# Build with increased memory limit
162+
export NODE_OPTIONS="--openssl-legacy-provider --max_old_space_size=4096"
163+
eas build --platform android --profile development --local --non-interactive --output=./app-dev.apk
164+
env:
165+
NODE_ENV: development
166+
167+
- name: 📱 Build Production APK
168+
if: github.event.inputs.buildType == 'all' || github.event.inputs.buildType == 'prod-apk' || github.event_name == 'push'
169+
run: |
170+
export NODE_OPTIONS="--openssl-legacy-provider --max_old_space_size=4096"
171+
eas build --platform android --profile production-apk --local --non-interactive --output=./app-prod.apk
172+
env:
173+
NODE_ENV: production
174+
175+
- name: 📱 Build Production AAB
176+
if: github.event.inputs.buildType == 'all' || github.event.inputs.buildType == 'prod-aab' || github.event_name == 'push'
177+
run: |
178+
export NODE_OPTIONS="--openssl-legacy-provider --max_old_space_size=4096"
179+
eas build --platform android --profile production --local --non-interactive --output=./app-prod.aab
180+
env:
181+
NODE_ENV: production
182+
183+
- name: 🏗 Setup rclone
184+
uses: AnimMouse/setup-rclone@v1
185+
with:
186+
version: latest
187+
188+
- name: 📤 Configure cloud storage
189+
run: |
190+
# Clean up any existing rclone config
191+
rm -rf ~/.config/rclone
192+
193+
# Create rclone config directory
194+
mkdir -p ~/.config/rclone
195+
196+
# Create rclone config file
197+
cat > ~/.config/rclone/rclone.conf << EOF
198+
[cloud]
199+
type = ${CLOUD_STORAGE_TYPE}
200+
region = com
201+
token = ${CLOUD_STORAGE_TOKEN}
202+
root_folder_id = ${CLOUD_STORAGE_ROOT_ID}
203+
EOF
204+
205+
# Set proper permissions
206+
chmod 600 ~/.config/rclone/rclone.conf
207+
208+
# Test configuration
209+
echo "Testing cloud storage configuration..."
210+
rclone ls cloud: --max-depth 1
211+
212+
- name: 📤 Upload Development APK to cloud storage
213+
if: github.event.inputs.buildType == 'all' || github.event.inputs.buildType == 'dev' || github.event_name == 'push'
214+
run: |
215+
VERSION=$(node -p "require('./app.json').expo.version")
216+
BUILD_NUMBER=$(date +%Y%m%d%H%M)
217+
FOLDER_PATH="App Builds/$VERSION-$BUILD_NUMBER"
218+
219+
# Create directory first
220+
echo "Creating folder: $FOLDER_PATH"
221+
rclone mkdir "cloud:$FOLDER_PATH"
222+
223+
# Copy APK file
224+
echo "Uploading development APK..."
225+
rclone copy ./app-dev.apk "cloud:$FOLDER_PATH/app-dev-$VERSION-$BUILD_NUMBER.apk" -v
226+
227+
- name: 📤 Upload Production APK to cloud storage
228+
if: github.event.inputs.buildType == 'all' || github.event.inputs.buildType == 'prod-apk' || github.event_name == 'push'
229+
run: |
230+
VERSION=$(node -p "require('./app.json').expo.version")
231+
BUILD_NUMBER=$(date +%Y%m%d%H%M)
232+
FOLDER_PATH="App Builds/$VERSION-$BUILD_NUMBER"
233+
234+
echo "Uploading production APK..."
235+
rclone copy ./app-prod.apk "cloud:$FOLDER_PATH/app-prod-$VERSION-$BUILD_NUMBER.apk" -v
236+
237+
- name: 📤 Upload Production AAB to cloud storage
238+
if: github.event.inputs.buildType == 'all' || github.event.inputs.buildType == 'prod-aab' || github.event_name == 'push'
239+
run: |
240+
VERSION=$(node -p "require('./app.json').expo.version")
241+
BUILD_NUMBER=$(date +%Y%m%d%H%M)
242+
FOLDER_PATH="App Builds/$VERSION-$BUILD_NUMBER"
243+
244+
echo "Uploading production AAB..."
245+
rclone copy ./app-prod.aab "cloud:$FOLDER_PATH/app-prod-$VERSION-$BUILD_NUMBER.aab" -v
246+
247+
- name: 📦 Upload build artifacts to GitHub
248+
uses: actions/upload-artifact@v4
249+
with:
250+
name: app-builds
251+
path: |
252+
./app-dev.apk
253+
./app-prod.apk
254+
./app-prod.aab
255+
retention-days: 7

0 commit comments

Comments
 (0)