name: 'Setup Flutter' description: 'Cross-platform setup for Flutter with local mirror and multi-runner concurrency support.' inputs: version: description: 'Flutter channel, version tag, or commit hash (e.g., master, stable, 3.29.0, 4ebf37fe7df0a130ba5bee17315b98f905c10b34). If omitted, automatically detected from .fvmrc or .fvm/fvm_config.json.' required: false default: '' mirror_url: description: 'Git repository URL for Flutter SDK' required: false default: 'https://git.rodydavis.dev/rodydavis/flutter.git' git_token: description: 'Gitea token for authenticated git cloning' required: false default: '' enable_windowing: description: 'Enable windowing and desktop support' required: false default: 'true' runs: using: 'composite' steps: - name: Install Flutter (macOS / Linux) if: runner.os != 'Windows' shell: bash run: | TARGET_VERSION="${{ inputs.version }}" if [ -z "$TARGET_VERSION" ]; then if [ -f ".fvmrc" ]; then TARGET_VERSION=$(grep -o '"flutter"[[:space:]]*:[[:space:]]*"[^"]*"' .fvmrc | head -n 1 | sed -E 's/.*"flutter"[[:space:]]*:[[:space:]]*"([^"]*)".*/\1/') elif [ -f ".fvm/fvm_config.json" ]; then TARGET_VERSION=$(grep -o '"flutterSdkVersion"[[:space:]]*:[[:space:]]*"[^"]*"' .fvm/fvm_config.json | head -n 1 | sed -E 's/.*"flutterSdkVersion"[[:space:]]*:[[:space:]]*"([^"]*)".*/\1/') if [ -z "$TARGET_VERSION" ]; then TARGET_VERSION=$(grep -o '"flutter"[[:space:]]*:[[:space:]]*"[^"]*"' .fvm/fvm_config.json | head -n 1 | sed -E 's/.*"flutter"[[:space:]]*:[[:space:]]*"([^"]*)".*/\1/') fi fi fi if [ -z "$TARGET_VERSION" ]; then TARGET_VERSION="master" fi echo "Resolved Flutter version: $TARGET_VERSION" LOCK_DIR="/opt/hostedtoolcache/flutter-sdk-setup.lock" if [ ! -d "/opt/hostedtoolcache" ] || [ ! -w "/opt/hostedtoolcache" ]; then LOCK_DIR="${TMPDIR:-/tmp}/flutter-sdk-setup.lock" fi for i in {1..60}; do if mkdir "$LOCK_DIR" 2>/dev/null; then break fi echo "Waiting for concurrent Flutter setup lock ($i/60)..." sleep 2 done SDK_DIR="$HOME/flutter-sdk" if [ -d "/opt/hostedtoolcache" ] && [ -w "/opt/hostedtoolcache" ]; then SDK_DIR="/opt/hostedtoolcache/flutter-sdk" fi CLONE_URL="${{ inputs.mirror_url }}" if [ -n "${{ inputs.git_token }}" ] && [[ "$CLONE_URL" == https://* ]]; then CLONE_URL="https://git:${{ inputs.git_token }}@${CLONE_URL#https://}" fi if [ ! -d "$SDK_DIR/.git" ] || [ ! -f "$SDK_DIR/bin/flutter" ]; then echo "Cloning Flutter SDK to $SDK_DIR..." rm -rf "$SDK_DIR" git clone "$CLONE_URL" "$SDK_DIR" || { echo "Failed to clone from mirror, falling back to GitHub..." git clone https://github.com/flutter/flutter.git "$SDK_DIR" } git -C "$SDK_DIR" config --global --add safe.directory "$SDK_DIR" || true git -C "$SDK_DIR" checkout "$TARGET_VERSION" else git -C "$SDK_DIR" config --global --add safe.directory "$SDK_DIR" || true CURRENT_COMMIT=$(git -C "$SDK_DIR" rev-parse HEAD 2>/dev/null || true) if [ "$CURRENT_COMMIT" != "$TARGET_VERSION" ] && [ "$TARGET_VERSION" != "master" ]; then echo "Checking out Flutter $TARGET_VERSION..." git -C "$SDK_DIR" fetch origin "$TARGET_VERSION" --depth=1 2>/dev/null || git -C "$SDK_DIR" fetch origin git -C "$SDK_DIR" checkout "$TARGET_VERSION" else echo "Flutter SDK already at $TARGET_VERSION. Ready to use." fi fi rm -rf "$LOCK_DIR" || true - name: Install Flutter (Windows) if: runner.os == 'Windows' shell: powershell run: | $targetVersion = "${{ inputs.version }}" if (-not $targetVersion) { if (Test-Path ".fvmrc") { try { $fvm = Get-Content ".fvmrc" | ConvertFrom-Json $targetVersion = $fvm.flutter } catch {} } elseif (Test-Path ".fvm\fvm_config.json") { try { $fvm = Get-Content ".fvm\fvm_config.json" | ConvertFrom-Json $targetVersion = if ($fvm.flutterSdkVersion) { $fvm.flutterSdkVersion } else { $fvm.flutter } } catch {} } } if (-not $targetVersion) { $targetVersion = "master" } Write-Output "Resolved Flutter version: $targetVersion" $lockDir = Join-Path $env:TEMP "flutter-sdk-setup.lock" $waited = 0 while ($true) { try { [System.IO.Directory]::CreateDirectory($lockDir) | Out-Null break } catch { Start-Sleep -Seconds 2 $waited += 2 if ($waited -ge 120) { break } } } $sdkDir = "C:\flutter-sdk" $cloneUrl = "${{ inputs.mirror_url }}" if ("${{ inputs.git_token }}" -ne "" -and $cloneUrl.StartsWith("https://")) { $cloneUrl = "https://git:${{ inputs.git_token }}@" + $cloneUrl.Substring(8) } if (-not (Test-Path "$sdkDir\bin\flutter.bat")) { echo "Cloning Flutter SDK to $sdkDir..." try { git clone $cloneUrl $sdkDir } catch { echo "Failed to clone from mirror, falling back to GitHub..." git clone https://github.com/flutter/flutter.git $sdkDir } git -C $sdkDir checkout $targetVersion } else { $currentCommit = git -C $sdkDir rev-parse HEAD 2>$null if ($currentCommit -ne $targetVersion -and $targetVersion -ne "master") { echo "Checking out Flutter $targetVersion..." git -C $sdkDir fetch origin git -C $sdkDir checkout $targetVersion } else { echo "Flutter SDK already at $targetVersion. Ready to use." } } if (Test-Path $lockDir) { try { [System.IO.Directory]::Delete($lockDir, $true) } catch {} } - name: Add to PATH and Configure (macOS / Linux) if: runner.os != 'Windows' shell: bash run: | SDK_DIR="$HOME/flutter-sdk" if [ -d "/opt/hostedtoolcache/flutter-sdk" ]; then SDK_DIR="/opt/hostedtoolcache/flutter-sdk" fi export PATH="$SDK_DIR/bin:$SDK_DIR/bin/cache/dart-sdk/bin:$PATH" echo "$SDK_DIR/bin" >> $GITHUB_PATH echo "$SDK_DIR/bin/cache/dart-sdk/bin" >> $GITHUB_PATH if [ "${{ inputs.enable_windowing }}" = "true" ]; then "$SDK_DIR/bin/flutter" config --enable-windowing fi "$SDK_DIR/bin/flutter" --version - name: Add to PATH and Configure (Windows) if: runner.os == 'Windows' shell: powershell run: | $sdkDir = "C:\flutter-sdk" [System.IO.File]::AppendAllText($env:GITHUB_PATH, "$sdkDir\bin`r`n") [System.IO.File]::AppendAllText($env:GITHUB_PATH, "$sdkDir\bin\cache\dart-sdk\bin`r`n") $env:PATH = "$sdkDir\bin;$sdkDir\bin\cache\dart-sdk\bin;$env:PATH" if ("${{ inputs.enable_windowing }}" -eq "true") { & "$sdkDir\bin\flutter.bat" config --enable-windowing } & "$sdkDir\bin\flutter.bat" --version