Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 48 additions & 8 deletions .github/workflows/mobile-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,7 @@ env:
IOS_PROV_PROFILE_DIRECTORY: "~/Library/MobileDevice/Provisioning\ Profiles/"

permissions:
contents: write
pull-requests: write
id-token: write
contents: read

on:
workflow_dispatch:
Expand Down Expand Up @@ -150,6 +148,8 @@ jobs:
# NOTE: Checks out the triggering branch (staging for PR merges, or the branch where manually triggered)
bump-version:
runs-on: ubuntu-latest
permissions:
contents: read
if: |
(github.event_name != 'pull_request' || github.event.pull_request.merged == true) &&
!contains(github.event.pull_request.labels.*.name, 'deploy:skip')
Expand Down Expand Up @@ -241,9 +241,26 @@ jobs:
echo "✅ Version bump calculated successfully"
echo "⚠️ Note: Changes are local only. Will be committed in PR after successful builds."

- name: Verify bump outputs were set
run: |
VERSION="${{ steps.bump.outputs.version }}"
IOS_BUILD="${{ steps.bump.outputs.ios_build }}"
ANDROID_BUILD="${{ steps.bump.outputs.android_build }}"

if [ -z "$VERSION" ] || [ -z "$IOS_BUILD" ] || [ -z "$ANDROID_BUILD" ]; then
echo "❌ Version bump failed to set required outputs"
echo "version='$VERSION', ios_build='$IOS_BUILD', android_build='$ANDROID_BUILD'"
exit 1
fi

echo "✅ All version outputs verified"

build-ios:
needs: [bump-version]
runs-on: macos-latest-large
permissions:
contents: read
actions: write
if: |
(github.event_name != 'pull_request' || github.event.pull_request.merged == true) &&
(
Expand Down Expand Up @@ -285,7 +302,7 @@ jobs:
echo "NODE_VERSION_SANITIZED=${VERSION//\//-}" >> "$GITHUB_ENV"

- name: Verify branch and commit (iOS)
if: inputs.platform != 'android'
if: needs.bump-version.outputs.platform != 'android'
run: |
echo "🔍 Verifying we're building from the correct branch and commit..."
echo "Current branch: $(git branch --show-current || git symbolic-ref --short HEAD 2>/dev/null || echo 'detached')"
Expand All @@ -309,7 +326,7 @@ jobs:
fi

- name: Apply version bump for build
if: inputs.platform != 'android'
if: needs.bump-version.outputs.platform != 'android'
run: |
cd ${{ env.APP_PATH }}

Expand Down Expand Up @@ -804,6 +821,10 @@ jobs:
build-android:
needs: [bump-version]
runs-on: ubuntu-latest
permissions:
contents: read
actions: write
id-token: write
if: |
(github.event_name != 'pull_request' || github.event.pull_request.merged == true) &&
(
Expand Down Expand Up @@ -910,7 +931,7 @@ jobs:
echo "NODE_VERSION_SANITIZED=${VERSION//\//-}" >> "$GITHUB_ENV"

- name: Verify branch and commit (Android)
if: inputs.platform != 'ios'
if: needs.bump-version.outputs.platform != 'ios'
run: |
echo "🔍 Verifying we're building from the correct branch and commit..."
echo "Current branch: $(git branch --show-current || git symbolic-ref --short HEAD 2>/dev/null || echo 'detached')"
Expand All @@ -930,7 +951,7 @@ jobs:
fi

- name: Apply version bump for build
if: inputs.platform != 'ios'
if: needs.bump-version.outputs.platform != 'ios'
run: |
cd ${{ env.APP_PATH }}

Expand Down Expand Up @@ -1234,6 +1255,9 @@ jobs:
# but create the version bump PR to dev so it can be reviewed before merging to staging
create-version-bump-pr:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
needs: [bump-version, build-ios, build-android]
if: |
always() &&
Expand Down Expand Up @@ -1284,6 +1308,20 @@ jobs:

echo "✅ Versions applied successfully"

- name: Verify version changes
run: |
cd ${{ env.APP_PATH }}

# Check that version files actually changed
if ! git diff --quiet package.json version.json; then
echo "✅ Version changes detected"
git diff package.json version.json
else
echo "⚠️ No version changes detected in package.json or version.json"
echo "This may indicate a problem with version application"
exit 1
fi

- name: Determine platforms that succeeded and PR title
id: platforms
run: |
Expand Down Expand Up @@ -1383,14 +1421,16 @@ jobs:

# Create git tags after successful deployment
create-release-tags:
runs-on: ubuntu-latest
permissions:
contents: write
needs: [bump-version, build-ios, build-android, create-version-bump-pr]
if: |
always() &&
(inputs.dry_run != true) &&
needs.create-version-bump-pr.result == 'success' &&
(needs.build-ios.result == 'success' || needs.build-android.result == 'success') &&
(inputs.deployment_track == 'production')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release-calendar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ jobs:
- name: Create dev to staging release PR
if: ${{ steps.guard_schedule.outputs.continue == 'true' && steps.check_dev_staging.outputs.existing_pr == '' }}
env:
GH_TOKEN: ${{ github.token }}
GH_TOKEN: ${{ secrets.SELFXYZ_INTERNAL_REPO_PAT }}
PR_DATE: ${{ steps.check_dev_staging.outputs.date }}
BRANCH_NAME: ${{ steps.check_dev_staging.outputs.branch_name }}
shell: bash
Expand Down Expand Up @@ -328,7 +328,7 @@ jobs:
- name: Create staging to main release PR
if: ${{ steps.guard_schedule.outputs.continue == 'true' && steps.production_status.outputs.staging_not_ahead != 'true' && steps.production_status.outputs.existing_pr == '' }}
env:
GH_TOKEN: ${{ github.token }}
GH_TOKEN: ${{ secrets.SELFXYZ_INTERNAL_REPO_PAT }}
PR_DATE: ${{ steps.production_status.outputs.date }}
COMMITS_AHEAD: ${{ steps.production_status.outputs.commits }}
shell: bash
Expand Down
20 changes: 10 additions & 10 deletions app/fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ ios_xcode_profile_path = "../ios/#{PROJECT_NAME}.xcodeproj"
default_platform(:ios)

platform :ios do
desc "Sync ios version"
desc "Sync ios version (DEPRECATED)"
lane :sync_version do
increment_version_number(
xcodeproj: "ios/#{PROJECT_NAME}.xcodeproj",
version_number: package_version,
)
UI.error("⛔ This lane is deprecated!")
UI.error("Version management is now centralized in CI.")
UI.error("Use: node scripts/version-manager.cjs apply <version> <ios> <android>")
UI.user_error!("sync_version lane is deprecated - use version-manager.cjs instead")
end

desc "Push a new build to TestFlight Internal Testing"
Expand Down Expand Up @@ -247,12 +247,12 @@ platform :ios do
end

platform :android do
desc "Sync android version"
desc "Sync android version (DEPRECATED)"
lane :sync_version do
android_set_version_name(
version_name: package_version,
gradle_file: android_gradle_file_path.gsub("../", ""),
)
UI.error("⛔ This lane is deprecated!")
UI.error("Version management is now centralized in CI.")
UI.error("Use: node scripts/version-manager.cjs apply <version> <ios> <android>")
UI.user_error!("sync_version lane is deprecated - use version-manager.cjs instead")
end

desc "Push a new build to Google Play Internal Testing"
Expand Down
20 changes: 18 additions & 2 deletions app/fastlane/helpers/version_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,26 @@ def verify_ci_version_match
android_matches = android_build == expected_android_build

unless version_matches && ios_matches && android_matches
UI.error("Version mismatch detected!")
UI.error("Version mismatch detected!")
UI.error("Expected: v#{expected_version} (iOS: #{expected_ios_build}, Android: #{expected_android_build})")
UI.error("Actual: v#{pkg_version} (iOS: #{ios_build}, Android: #{android_build})")
UI.user_error!("Version mismatch! CI version-manager script should have set these correctly.")
UI.error("")

# Add specific diagnostics
UI.error("Mismatched fields:")
UI.error(" • package.json version") unless version_matches
UI.error(" • version.json iOS build") unless ios_matches
UI.error(" • version.json Android build") unless android_matches
UI.error("")

UI.error("💡 Common causes:")
UI.error(" 1. version-manager.cjs 'apply' command didn't run in workflow")
UI.error(" 2. Files were modified after version bump was applied")
UI.error(" 3. CI_VERSION, CI_IOS_BUILD, or CI_ANDROID_BUILD env vars are incorrect")
UI.error("")
UI.error("🔍 Debug: Check workflow logs for 'Apply version bump' step")

UI.user_error!("Version verification failed")
end

UI.success("✅ Version verification passed:")
Expand Down
11 changes: 9 additions & 2 deletions app/jest.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,19 @@

module.exports = {
preset: 'react-native',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'cjs', 'json', 'node'],
transformIgnorePatterns: [
'node_modules/(?!(react-native|@react-native|@react-navigation|@react-native-community|@segment/analytics-react-native|@openpassport|react-native-keychain|react-native-check-version|react-native-nfc-manager|react-native-passport-reader|react-native-gesture-handler|uuid|@stablelib|@react-native-google-signin|react-native-cloud-storage|@react-native-clipboard|@react-native-firebase|@selfxyz|@sentry|@anon-aadhaar|react-native-svg|react-native-svg-circle-country-flags)/)',
],
setupFiles: ['<rootDir>/jest.setup.js'],
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.[jt]sx?$',
testMatch: [
'<rootDir>/**/__tests__/**/*.{js,jsx,ts,tsx,cjs}',
'<rootDir>/**/?(*.)+(spec|test).{js,jsx,ts,tsx,cjs}',
],
testPathIgnorePatterns: [
'/node_modules/',
'/scripts/tests/', // Node.js native test runner tests
],
moduleNameMapper: {
'^@env$': '<rootDir>/tests/__setup__/@env.js',
'\\.svg$': '<rootDir>/tests/__setup__/svgMock.js',
Expand Down
31 changes: 27 additions & 4 deletions app/scripts/version-manager.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,33 @@ function bumpVersion(bumpType, platform = 'both') {
* Apply version changes to files
*/
function applyVersions(version, iosBuild, androidBuild) {
// Validate version format (semver X.Y.Z)
if (
!version ||
typeof version !== 'string' ||
!/^\d+\.\d+\.\d+$/.test(version)
) {
throw new Error(`Invalid version format: ${version}. Expected X.Y.Z`);
}

// Validate and coerce build numbers
const iosNum = Number(iosBuild);
const androidNum = Number(androidBuild);

if (!Number.isInteger(iosNum) || iosNum < 1) {
throw new Error(`Invalid iOS build: ${iosBuild}. Must be positive integer`);
}

if (!Number.isInteger(androidNum) || androidNum < 1) {
throw new Error(
`Invalid Android build: ${androidBuild}. Must be positive integer`,
);
}

console.log(`📝 Applying versions to files...`);
console.log(` Version: ${version}`);
console.log(` iOS Build: ${iosBuild}`);
console.log(` Android Build: ${androidBuild}`);
console.log(` iOS Build: ${iosNum}`);
console.log(` Android Build: ${androidNum}`);

// Update package.json
const pkg = readPackageJson();
Expand All @@ -217,8 +240,8 @@ function applyVersions(version, iosBuild, androidBuild) {

// Update version.json
const versionData = readVersionJson();
versionData.ios.build = iosBuild;
versionData.android.build = androidBuild;
versionData.ios.build = iosNum;
versionData.android.build = androidNum;
writeVersionJson(versionData);
console.log(`✅ Updated version.json`);
}
Expand Down
Loading
Loading