GiantCroissant.Lunar.Build.Mobile 0.1.1-ci.113

This is a prerelease version of GiantCroissant.Lunar.Build.Mobile.
dotnet add package GiantCroissant.Lunar.Build.Mobile --version 0.1.1-ci.113
                    
NuGet\Install-Package GiantCroissant.Lunar.Build.Mobile -Version 0.1.1-ci.113
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="GiantCroissant.Lunar.Build.Mobile" Version="0.1.1-ci.113" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="GiantCroissant.Lunar.Build.Mobile" Version="0.1.1-ci.113" />
                    
Directory.Packages.props
<PackageReference Include="GiantCroissant.Lunar.Build.Mobile" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add GiantCroissant.Lunar.Build.Mobile --version 0.1.1-ci.113
                    
#r "nuget: GiantCroissant.Lunar.Build.Mobile, 0.1.1-ci.113"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package GiantCroissant.Lunar.Build.Mobile@0.1.1-ci.113
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=GiantCroissant.Lunar.Build.Mobile&version=0.1.1-ci.113&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=GiantCroissant.Lunar.Build.Mobile&version=0.1.1-ci.113&prerelease
                    
Install as a Cake Tool

RFC030: Mobile Component with Integrated Fastlane

NUKE Fastlane RFC030

This package implements RFC030, providing NUKE-native mobile build interfaces that integrate seamlessly with Fastlane automation for iOS and Android deployment. It replaces the deprecated RFC018 complex component system with clean, composable NUKE interfaces.

🏗️ Architecture Overview

RFC030 provides a hybrid architecture combining:

  • NUKE Orchestration: Build dependencies, parameter management, error handling
  • Fastlane Expertise: Mobile platform knowledge, store deployment, certificate management
  • Template Distribution: Standardized mobile deployment patterns via NuGet
  • Developer Experience: Single command mobile deployment with proper orchestration

📦 Package Contents

Core Interfaces (NUKE-native)

  • IMobileBuild: Base mobile interface with common parameters and functionality
  • IiOSBuild: iOS-specific build and deployment interface with TestFlight/App Store integration
  • IAndroidBuild: Android-specific build and deployment interface with Google Play integration

Services

  • IFastlaneExecutionService: NUKE-integrated Fastlane execution bridge
  • IFastlaneRunner: Core Fastlane command execution service
  • IFastlaneTemplateInstaller: Template installation and management service

Templates (Embedded Resources)

  • Fastfile.ios: Comprehensive iOS build automation with TestFlight, Firebase, App Store
  • Fastfile.android: Complete Android build automation with Google Play, Firebase
  • Gemfile template: Ruby dependency management
  • Environment templates: Platform-specific environment variable examples

🚀 Quick Start

1. Add NuGet Package Reference

<PackageReference Include="GiantCroissant.Lunar.Build.Mobile" Version="*" />

2. Implement Mobile Interfaces

using Lunar.Build.Interfaces;
using Microsoft.Extensions.DependencyInjection;

public class Build : NukeBuild, IiOSBuild, IAndroidBuild
{
    // NUKE will automatically provide all mobile parameters via [ParameterPrefix] attributes
    
    public override void ConfigureServices(IServiceCollection services)
    {
        base.ConfigureServices(services);
        
        // Add mobile services with configuration
        services.AddMobileServices(config =>
        {
            config.FastlanePath = "fastlane";
            config.UseBundleExec = true;
        });
    }
}

3. Use Mobile Build Targets

# Build iOS application
nuke BuildiOS --ios-bundle-id com.yourcompany.app --ios-team-id YOUR_TEAM_ID

# Build Android application
nuke BuildAndroid --android-package-name com.yourcompany.app

# Deploy to TestFlight
nuke UploadTestFlight --app-store-api-key-id YOUR_KEY_ID --app-store-api-key-path ./AuthKey.p8

# Deploy to Google Play
nuke UploadGooglePlay --google-play-service-account-path ./service-account.json

# Complete CI/CD pipeline
nuke MobileCIPipeline

🍎 iOS Integration

Available Targets

Target Description Dependencies
BuildiOS Build iOS application ValidateMobileEnvironment, CleanMobileOutput
TestiOS Run iOS unit/UI tests BuildiOS (optional)
UploadTestFlight Upload to TestFlight BuildiOS (optional)
UploadFirebase Upload to Firebase App Distribution BuildiOS (optional)
SubmitAppStore Submit to App Store BuildiOS (optional)

Key Parameters

[Parameter] string iOSBundleId => "com.giantcroissant.app";
[Parameter] string iOSTeamId => TryGetValue(() => iOSTeamId);
[Parameter] string iOSScheme => "Unity-iPhone";
[Parameter] string iOSExportMethod => "development"; // development, ad-hoc, enterprise, app-store
[Parameter] AbsolutePath iOSProjectPath => RootDirectory / "ios";
[Parameter] string AppStoreApiKeyId => TryGetValue(() => AppStoreApiKeyId);
[Parameter] AbsolutePath AppStoreApiKeyPath => TryGetValue(() => AppStoreApiKeyPath);
[Parameter] string FirebaseAppId => TryGetValue(() => FirebaseAppId);

iOS Fastlane Integration

The iOS interface automatically executes Fastlane lanes:

# Fastfile.ios lanes used by RFC030
lane :build do |options|
  # Comprehensive iOS build with signing, version management, export
end

lane :test do |options|
  # iOS unit and UI testing with simulators
end

lane :upload_testflight do |options|
  # TestFlight upload with App Store Connect API
end

lane :upload_firebase do |options|
  # Firebase App Distribution deployment
end

🤖 Android Integration

Available Targets

Target Description Dependencies
BuildAndroid Build Android APK/AAB ValidateMobileEnvironment, CleanMobileOutput
BuildAndroidBundle Build Android App Bundle (AAB) ValidateMobileEnvironment, CleanMobileOutput
TestAndroid Run Android unit/instrumentation tests BuildAndroid (optional)
UploadGooglePlay Upload to Google Play Console BuildAndroid (optional)
UploadFirebaseAndroid Upload to Firebase App Distribution BuildAndroid (optional)

Key Parameters

[Parameter] string AndroidPackageName => "com.giantcroissant.app";
[Parameter] string AndroidBuildVariant => "release"; // debug, release
[Parameter] string AndroidBuildType => "apk"; // apk, bundle
[Parameter] AbsolutePath AndroidProjectPath => RootDirectory / "android";
[Parameter] AbsolutePath AndroidKeystorePath => TryGetValue(() => AndroidKeystorePath);
[Parameter] [Secret] string AndroidKeystorePassword => TryGetValue(() => AndroidKeystorePassword);
[Parameter] AbsolutePath GooglePlayServiceAccountPath => TryGetValue(() => GooglePlayServiceAccountPath);
[Parameter] string GooglePlayTrack => "internal"; // internal, alpha, beta, production

Android Fastlane Integration

The Android interface automatically executes Fastlane lanes:

# Fastfile.android lanes used by RFC030
lane :build do |options|
  # Comprehensive Android build with signing, ProGuard, version management
end

lane :unit_test do |options|
  # Android unit testing with JUnit
end

lane :deploy_play_store do |options|
  # Google Play Console deployment with tracks
end

lane :deploy_firebase do |options|
  # Firebase App Distribution deployment
end

⚙️ Service Configuration

Dependency Injection Setup

public override void ConfigureServices(IServiceCollection services)
{
    base.ConfigureServices(services);

    // Basic mobile services
    services.AddMobileServices();

    // Advanced configuration
    services.AddMobileServices(config =>
    {
        config.FastlanePath = "fastlane";
        config.UseBundleExec = true;
        config.GlobalEnvironmentVariables = new Dictionary<string, string>
        {
            ["FASTLANE_SKIP_UPDATE_CHECK"] = "1",
            ["FASTLANE_DISABLE_ANIMATION"] = "1"
        };
        
        // iOS-specific settings
        config.iOS.FastlanePath = "ios/fastlane";
        
        // Android-specific settings  
        config.Android.FastlanePath = "android/fastlane";
    });

    // Platform-specific services
    services.AddiOSServices(ios =>
    {
        ios.FastlanePath = "ios/fastlane";
    });

    services.AddAndroidServices(android =>
    {
        android.FastlanePath = "android/fastlane";
    });
}

Service Usage in Targets

Target CustomMobileTarget => _ => _
    .Executes(async () =>
    {
        // Get mobile services helper
        var mobileServices = ServiceProvider.GetMobileServices();
        
        // Validate environment
        var validation = await mobileServices.ValidateEnvironmentAsync(MobilePlatform.iOS);
        
        // Execute custom lane
        var parameters = new Dictionary<string, string>
        {
            ["custom_param"] = "value"
        };
        
        var result = await mobileServices.ExecuteLaneAsync("ios", "custom_lane", parameters);
        
        if (!result.IsSuccess)
        {
            throw new InvalidOperationException($"Custom lane failed: {result.ErrorMessage}");
        }
    });

📋 Template Management

Automatic Template Installation

Templates are automatically installed when needed, but you can also manage them explicitly:

Target InstallTemplates => _ => _
    .Executes(async () =>
    {
        var mobileServices = ServiceProvider.GetMobileServices();
        
        // Install iOS templates
        var iOSResult = await mobileServices.TemplateInstaller.InstallTemplatesAsync(
            targetDirectory: "ios",
            platform: MobilePlatform.iOS,
            options: new FastlaneTemplateOptions
            {
                InstallGemfile = true,
                InstallEnvironmentTemplate = true,
                OverwriteExisting = false,
                Customizations = new Dictionary<string, string>
                {
                    ["app_identifier"] = iOSBundleId,
                    ["team_id"] = iOSTeamId ?? ""
                }
            });
        
        // Install Android templates
        var androidResult = await mobileServices.TemplateInstaller.InstallTemplatesAsync(
            targetDirectory: "android",
            platform: MobilePlatform.Android,
            options: new FastlaneTemplateOptions
            {
                InstallGemfile = true,
                InstallEnvironmentTemplate = true,
                Customizations = new Dictionary<string, string>
                {
                    ["package_name"] = AndroidPackageName
                }
            });
    });

Template Status Checking

Target CheckTemplateStatus => _ => _
    .Executes(async () =>
    {
        var installer = ServiceProvider.GetRequiredService<IFastlaneTemplateInstaller>();
        
        var status = await installer.CheckTemplateStatusAsync("ios", MobilePlatform.iOS);
        
        Log.Information("Template Status: {Status}", status.IsInstalled ? "Installed" : "Missing");
        Log.Information("Up to Date: {UpToDate}", status.IsUpToDate);
        Log.Information("Message: {Message}", status.Message);
    });

🔧 Advanced Usage

Custom Mobile Orchestration

public class AdvancedMobileBuild : NukeBuild, IiOSBuild, IAndroidBuild
{
    Target BuildAllPlatforms => _ => _
        .Description("Build all mobile platforms with custom logic")
        .DependsOn(ValidateMobileEnvironment)
        .Executes(async () =>
        {
            var platforms = new[] { "iOS", "Android" };
            var tasks = new List<Task<bool>>();
            
            foreach (var platform in platforms)
            {
                tasks.Add(BuildPlatformAsync(platform));
            }
            
            var results = await Task.WhenAll(tasks);
            var successCount = results.Count(r => r);
            
            Log.Information("✅ {SuccessCount}/{TotalCount} platforms built successfully", 
                successCount, platforms.Length);
                
            if (successCount < platforms.Length)
            {
                throw new InvalidOperationException("One or more platform builds failed");
            }
        });

    private async Task<bool> BuildPlatformAsync(string platform)
    {
        try
        {
            var mobileServices = ServiceProvider.GetMobileServices();
            var parameters = CreatePlatformParameters(platform);
            
            var result = await mobileServices.ExecuteLaneAsync(
                platform.ToLowerInvariant(), 
                "build", 
                parameters, 
                FastlaneWorkingDirectory);
            
            return result.IsSuccess;
        }
        catch (Exception ex)
        {
            Log.Error(ex, "❌ {Platform} build failed", platform);
            return false;
        }
    }
}

Environment-Specific Deployment

Target DeployByEnvironment => _ => _
    .Executes(() =>
    {
        var environment = Environment.GetEnvironmentVariable("BUILD_ENVIRONMENT") ?? "development";
        
        Log.Information("🚀 Deploying to {Environment} environment", environment);
        
        var deploymentTargets = environment.ToLowerInvariant() switch
        {
            "production" => new[] { UploadTestFlight, UploadGooglePlay },
            "staging" => new[] { UploadFirebase, UploadFirebaseAndroid },
            "development" => new[] { UploadFirebase, UploadFirebaseAndroid },
            _ => throw new InvalidOperationException($"Unknown environment: {environment}")
        };
        
        foreach (var target in deploymentTargets)
        {
            try
            {
                target.Invoke();
            }
            catch (Exception ex)
            {
                Log.Error(ex, "❌ Deployment target failed: {Target}", target.Name);
                throw;
            }
        }
    });

🔍 Troubleshooting

Common Issues

1. Fastlane Not Found
Error: Fastlane not available or not properly configured

Solution: Install Fastlane using gem or bundle:

gem install fastlane
# or
bundle install
2. Template Installation Failed
Error: Could not find Fastfile template for iOS

Solution: Templates are embedded in the NuGet package. Verify package installation:

dotnet list package | grep Lunar.Build.Mobile
3. iOS Code Signing Issues
Error: Code signing failed

Solutions:

  • Verify Team ID: --ios-team-id YOUR_TEAM_ID
  • Configure Match: --match-git-url https://github.com/yourcompany/certificates
  • Use automatic signing: --automatic-code-signing true
4. Android Signing Issues
Error: Android signing configuration is incomplete

Solutions:

  • Provide keystore: --android-keystore-path ./release.keystore
  • Set passwords via environment variables:
    export ANDROID_KEYSTORE_PASSWORD=your_password
    export ANDROID_KEY_PASSWORD=your_key_password
    

Debug Mode

Enable verbose logging for troubleshooting:

nuke BuildiOS --verbosity verbose

Or set log level in build:

public override LogLevel LogLevel => LogLevel.Debug;

🤝 Contributing

This component follows the NUKE-native interface pattern established in the critical architectural pivot (August 2025). When contributing:

  1. Follow NUKE Patterns: Use [ParameterPrefix], TryGetValue(), TryDependsOn<T>()
  2. Interface Composition: Clean interface composition for mobile builds
  3. Service Integration: Use dependency injection for service management
  4. Template Management: Maintain embedded Fastlane templates as resources

📄 License

This component is part of the GiantCroissant Lunar Build System and follows the same licensing terms.


RFC030: Mobile Component with Integrated Fastlane - Bringing NUKE orchestration and Fastlane expertise together for seamless mobile deployment automation.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on GiantCroissant.Lunar.Build.Mobile:

Package Downloads
GiantCroissant.Lunar.Build

Meta-package that depends on the Lunar Build component packages for one-line install.

GiantCroissant.Lunar.Build.Mobile.Android

RFC020: Android Build Integration - Comprehensive Android build support with Gradle, signing, and deployment capabilities

GiantCroissant.Lunar.Build.Mobile.iOS

RFC021: iOS build component with comprehensive iOS build support including Xcode integration, code signing, TestFlight deployment, and Firebase App Distribution

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.1-ci.113 114 10/7/2025
0.1.1-ci.112 120 10/7/2025
0.1.1-ci.111 210 9/15/2025
0.1.1-ci.110 197 9/15/2025
0.1.1-ci.109 197 9/15/2025
0.1.1-ci.108 202 9/15/2025
0.1.1-ci.107 197 9/15/2025
0.1.1-ci.104 173 9/15/2025
0.1.1-ci.90 121 9/8/2025
0.1.1-ci.40 61 9/6/2025
0.1.1-ci.21 135 9/4/2025
0.1.1-ci.20 137 9/3/2025
0.1.1-chore-ci-pack-mobile-... 36 9/4/2025