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

This is a prerelease version of GiantCroissant.Lunar.Build.Mobile.
dotnet add package GiantCroissant.Lunar.Build.Mobile --version 0.1.1-ci.90
                    
NuGet\Install-Package GiantCroissant.Lunar.Build.Mobile -Version 0.1.1-ci.90
                    
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.90" />
                    
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.90" />
                    
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.90
                    
#r "nuget: GiantCroissant.Lunar.Build.Mobile, 0.1.1-ci.90"
                    
#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.90
                    
#: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.90&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=GiantCroissant.Lunar.Build.Mobile&version=0.1.1-ci.90&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.Mobile.iOS

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

GiantCroissant.Lunar.Build.Mobile.Android

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

GiantCroissant.Lunar.Build

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

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.1-ci.90 72 9/8/2025
0.1.1-ci.40 54 9/6/2025
0.1.1-ci.21 128 9/4/2025
0.1.1-ci.20 133 9/3/2025
0.1.1-chore-ci-pack-mobile-... 33 9/4/2025