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
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Validation workflows: **`ubuntu-latest`** runs on every PR targeting `main` (wit
- **Tool wrappers**: copy/paste from neighbours; cover full commands; use `<c>`, `<a>`, `<ul>`/`<ol>`, `<em>`, `<para/>` in `help`; don't write `secret: false` or `default: xxx`.
- **Tests next to code, separate folder**: every `Foo` project under `src/` has a sibling `Foo.Tests` project under `tests/`. Mirror the namespace.
- **No IDE-specific style files committed.** `.editorconfig` and `*.DotSettings` were removed during the takeover — relying on `dotnet format` defaults and review.
- **Telemetry opt-out is set in test runs** (`NUKE_TELEMETRY_OPTOUT=true`). Keep it that way.
- **Telemetry opt-out is set in test runs** (`FALLOUT_TELEMETRY_OPTOUT=true`). Keep it that way.
- **License header**: every source file starts with the 4-line `// Copyright … Maintainers of Fallout. // Originally based on NUKE …` block — copy from a neighbouring file when adding new ones.

## What not to do
Expand Down
2 changes: 1 addition & 1 deletion build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ $DotNetChannel = "STS"
$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1
$env:DOTNET_NOLOGO = 1
$env:DOTNET_ROLL_FORWARD = "Major"
$env:NUKE_TELEMETRY_OPTOUT = 1
$env:FALLOUT_TELEMETRY_OPTOUT = 1

###########################################################################
# EXECUTION
Expand Down
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ DOTNET_CHANNEL="STS"
export DOTNET_CLI_TELEMETRY_OPTOUT=1
export DOTNET_NOLOGO=1
export DOTNET_ROLL_FORWARD="Major"
export NUKE_TELEMETRY_OPTOUT=1
export FALLOUT_TELEMETRY_OPTOUT=1

###########################################################################
# EXECUTION
Expand Down
2 changes: 1 addition & 1 deletion build/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ from framework in project.GetTargetFrameworks()
public int TestDegreeOfParallelism { get; } = 1;

Configure<DotNetTestSettings> ITest.TestSettings => _ => _
.SetProcessEnvironmentVariable("NUKE_TELEMETRY_OPTOUT", bool.TrueString);
.SetProcessEnvironmentVariable("FALLOUT_TELEMETRY_OPTOUT", bool.TrueString);

Target ITest.Test => _ => _
.Inherit<ITest>()
Expand Down
8 changes: 4 additions & 4 deletions build/_build.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@
<LangVersion>preview</LangVersion>
<RootNamespace></RootNamespace>
<NoWarn>CS0649;CS0169</NoWarn>
<NukeRootDirectory>.\..</NukeRootDirectory>
<NukeTelemetryVersion>1</NukeTelemetryVersion>
<FalloutRootDirectory>.\..</FalloutRootDirectory>
<FalloutTelemetryVersion>1</FalloutTelemetryVersion>
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
<IsPackable>false</IsPackable>
</PropertyGroup>

<!-- Test properties for MSBuild integration -->
<PropertyGroup>
<NukeTasksEnabled Condition="'$(NukeTasksEnabled)' == ''">False</NukeTasksEnabled>
<NukeTasksDirectory>$(MSBuildThisFileDirectory)\..\src\Fallout.MSBuildTasks\bin\Debug\net8.0\publish</NukeTasksDirectory>
<FalloutTasksEnabled Condition="'$(FalloutTasksEnabled)' == ''">False</FalloutTasksEnabled>
<FalloutTasksDirectory>$(MSBuildThisFileDirectory)\..\src\Fallout.MSBuildTasks\bin\Debug\net8.0\publish</FalloutTasksDirectory>

<!-- <PackAsTool>True</PackAsTool>-->
<!-- <ToolCommandName>build</ToolCommandName>-->
Expand Down
2 changes: 1 addition & 1 deletion docs/01-getting-started/07-telemetry.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,4 @@ Whenever a type does not originate from the `Nuke` namespace, it is replaced wit

## How to opt out

The telemetry feature is enabled by default. To opt out, set the `NUKE_TELEMETRY_OPTOUT` environment variable to `1` or `true`.
The telemetry feature is enabled by default. To opt out, set the `FALLOUT_TELEMETRY_OPTOUT` environment variable to `1` or `true`. The legacy `NUKE_TELEMETRY_OPTOUT` name is still honoured during the 10.x line for backwards compatibility, but will be removed in 11.0.
19 changes: 16 additions & 3 deletions src/Fallout.Build.Shared/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,15 @@ internal static class Constants
internal const string ParametersFilePrefix = "parameters";
internal const string DefaultProfileName = "$default";

internal const string GlobalToolVersionEnvironmentKey = "NUKE_GLOBAL_TOOL_VERSION";
internal const string GlobalToolStartTimeEnvironmentKey = "NUKE_GLOBAL_TOOL_START_TIME";
internal const string InterceptorEnvironmentKey = "NUKE_INTERNAL_INTERCEPTOR";
internal const string GlobalToolVersionEnvironmentKey = "FALLOUT_GLOBAL_TOOL_VERSION";
internal const string GlobalToolStartTimeEnvironmentKey = "FALLOUT_GLOBAL_TOOL_START_TIME";
internal const string InterceptorEnvironmentKey = "FALLOUT_INTERNAL_INTERCEPTOR";

// Legacy NUKE_* env var names — readers fall back to these via LegacyEnvironment.Read.
// Writers (e.g. global tool spawning the build) only emit the FALLOUT_* form above.
internal const string LegacyGlobalToolVersionEnvironmentKey = "NUKE_GLOBAL_TOOL_VERSION";
internal const string LegacyGlobalToolStartTimeEnvironmentKey = "NUKE_GLOBAL_TOOL_START_TIME";
internal const string LegacyInterceptorEnvironmentKey = "NUKE_INTERNAL_INTERCEPTOR";

// Canonical project URLs. Until P7 (domain registration) lands, these all point at the GitHub fork.
// To migrate to fallout.<tld>, edit FalloutWebsite / FalloutRepository here — call sites already use the constants.
Expand Down Expand Up @@ -155,6 +161,13 @@ public static IEnumerable<string> GetProfileNames(AbsolutePath rootDirectory)
}

internal static string GetCredentialStoreName(AbsolutePath rootDirectory, [CanBeNull] string profile)
{
return $"Fallout: {rootDirectory} ({profile ?? DefaultProfileName})";
}

// Pre-rename name. Readers fall back to this when the canonical entry is missing.
// Writers (SavePassword / Secrets command) only emit the canonical form above.
internal static string GetLegacyCredentialStoreName(AbsolutePath rootDirectory, [CanBeNull] string profile)
{
return $"NUKE: {rootDirectory} ({profile ?? DefaultProfileName})";
}
Expand Down
66 changes: 66 additions & 0 deletions src/Fallout.Build.Shared/LegacyEnvironment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright 2026 Maintainers of Fallout.
// Originally based on NUKE by Matthias Koch and contributors.
// Distributed under the MIT License.
// https://github.com/ChrisonSimtian/Fallout/blob/main/LICENSE

using System;
using System.Collections.Generic;

namespace Fallout.Common;

/// <summary>
/// Helpers for reading environment variables during the NUKE → Fallout rename.
/// Reads the preferred (FALLOUT_*) name first, falls back to the legacy (NUKE_*)
/// name if only the legacy is set, and emits a one-time warning per legacy key.
/// </summary>
internal static class LegacyEnvironment
{
private static readonly HashSet<string> WarnedLegacyKeys = new(StringComparer.Ordinal);
private static readonly object WarnedLegacyKeysLock = new();

/// <summary>
/// Returns the value of <paramref name="preferredName"/> if set; otherwise the value of
/// <paramref name="legacyName"/> (with a deprecation warning); otherwise <c>null</c>.
/// </summary>
public static string Read(string preferredName, string legacyName)
{
var preferred = Environment.GetEnvironmentVariable(preferredName);
if (!string.IsNullOrEmpty(preferred))
return preferred;

var legacy = Environment.GetEnvironmentVariable(legacyName);
if (string.IsNullOrEmpty(legacy))
return null;

WarnOnce(legacyName, preferredName);
return legacy;
}

/// <summary>
/// Same as <see cref="Read"/> but for the dictionary-style access used by EnvironmentInfo.Variables.
/// </summary>
public static string ReadFromVariables(IReadOnlyDictionary<string, string> variables, string preferredName, string legacyName)
{
if (variables.TryGetValue(preferredName, out var preferred) && !string.IsNullOrEmpty(preferred))
return preferred;

if (!variables.TryGetValue(legacyName, out var legacy) || string.IsNullOrEmpty(legacy))
return null;

WarnOnce(legacyName, preferredName);
return legacy;
}

private static void WarnOnce(string legacyName, string preferredName)
{
lock (WarnedLegacyKeysLock)
{
if (!WarnedLegacyKeys.Add(legacyName))
return;
}

Console.Error.WriteLine(
$"warning FALLOUT002: Environment variable '{legacyName}' is deprecated; rename to '{preferredName}'. " +
"The legacy name still works in 10.x but will be removed in 11.0.");
}
}
2 changes: 1 addition & 1 deletion src/Fallout.Build/FalloutBuild.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ ExecutionStatus.Aborted or
/// </summary>
public int? ExitCode { get; set; }

private bool IsInterceptorExecution => Environment.GetEnvironmentVariable(InterceptorEnvironmentKey) == "1";
private bool IsInterceptorExecution => LegacyEnvironment.Read(InterceptorEnvironmentKey, LegacyInterceptorEnvironmentKey) == "1";

public void ReportSummary(Configure<Dictionary<string, string>> configurator = null)
{
Expand Down
14 changes: 10 additions & 4 deletions src/Fallout.Build/Telemetry/Telemetry.Properties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,12 @@ private static Dictionary<string, string> GetCommonProperties(IFalloutBuild buil
["os_platform"] = EnvironmentInfo.Platform.ToString(),
["os_architecture"] = RuntimeInformation.OSArchitecture.ToString(),
["version_dotnet_sdk"] = version,
["version_nuke_common"] = build != null ? typeof(FalloutBuild).Assembly.GetVersionText() : null,
["version_nuke_global_tool"] = build != null
? EnvironmentInfo.Variables.GetValueOrDefault(Constants.GlobalToolVersionEnvironmentKey)
["version_fallout_common"] = build != null ? typeof(FalloutBuild).Assembly.GetVersionText() : null,
["version_fallout_global_tool"] = build != null
? LegacyEnvironment.ReadFromVariables(
EnvironmentInfo.Variables,
Constants.GlobalToolVersionEnvironmentKey,
Constants.LegacyGlobalToolVersionEnvironmentKey)
: Assembly.GetEntryAssembly().GetVersionText()
};
}
Expand Down Expand Up @@ -80,7 +83,10 @@ private static Dictionary<string, string> GetRepositoryProperties(string directo

private static ReadOnlyDictionary<string, string> GetBuildProperties(IFalloutBuild build)
{
var startTimeString = EnvironmentInfo.Variables.GetValueOrDefault(Constants.GlobalToolStartTimeEnvironmentKey);
var startTimeString = LegacyEnvironment.ReadFromVariables(
EnvironmentInfo.Variables,
Constants.GlobalToolStartTimeEnvironmentKey,
Constants.LegacyGlobalToolStartTimeEnvironmentKey);
var compileTime = startTimeString != null
? DateTime.Now.Subtract(DateTime.Parse(startTimeString))
: default(TimeSpan?);
Expand Down
13 changes: 9 additions & 4 deletions src/Fallout.Build/Telemetry/Telemetry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,26 @@ internal static partial class Telemetry
// https://docs.microsoft.com/en-us/azure/azure-monitor/app/console
// https://docs.microsoft.com/en-us/azure/azure-monitor/app/ip-collection

public const string OptOutEnvironmentKey = "NUKE_TELEMETRY_OPTOUT";
public const string OptOutEnvironmentKey = "FALLOUT_TELEMETRY_OPTOUT";
public const string LegacyOptOutEnvironmentKey = "NUKE_TELEMETRY_OPTOUT";
public const int CurrentVersion = 1;

// Telemetry is currently a no-op for Fallout: the previous InstrumentationKey routed data
// to the original NUKE maintainer's Azure Application Insights, which we don't own and shouldn't
// populate. When/if we stand up a Fallout-controlled endpoint, fill in the key here.
// Original NUKE key (do NOT reuse): "4b987be9-f807-4846-b777-4291f3a5ad8b"
private const string InstrumentationKey = "";
private const string VersionPropertyName = "NukeTelemetryVersion";
private const string VersionPropertyName = "FalloutTelemetryVersion";
private const string LegacyVersionPropertyName = "NukeTelemetryVersion";

private static readonly TelemetryClient s_client;
private static readonly int? s_confirmedVersion;

static Telemetry()
{
var optoutParameter = ParameterService.GetParameter<string>(OptOutEnvironmentKey) ?? string.Empty;
var optoutParameter = ParameterService.GetParameter<string>(OptOutEnvironmentKey)
?? ParameterService.GetParameter<string>(LegacyOptOutEnvironmentKey)
?? string.Empty;
if (optoutParameter == "1" || optoutParameter.EqualsOrdinalIgnoreCase(bool.TrueString))
return;

Expand Down Expand Up @@ -80,7 +84,8 @@ AbsolutePath GetCookieFile(string name, int version)
}

var project = ProjectModelTasks.ParseProject(FalloutBuild.BuildProjectFile);
var property = project.Properties.SingleOrDefault(x => x.Name.EqualsOrdinalIgnoreCase(VersionPropertyName));
var property = project.Properties.SingleOrDefault(x => x.Name.EqualsOrdinalIgnoreCase(VersionPropertyName))
?? project.Properties.SingleOrDefault(x => x.Name.EqualsOrdinalIgnoreCase(LegacyVersionPropertyName));
if (property?.EvaluatedValue != CurrentVersion.ToString())
{
if (FalloutBuild.IsServerBuild)
Expand Down
17 changes: 17 additions & 0 deletions src/Fallout.Build/Utilities/CredentialStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,29 @@ string PromptForPassword()
}

var credentialStoreName = Constants.GetCredentialStoreName(rootDirectory, profile);
var legacyCredentialStoreName = Constants.GetLegacyCredentialStoreName(rootDirectory, profile);
var passwordParameterName = Constants.GetProfilePasswordParameterName(profile);

return TryGetPassword(credentialStoreName) ??
TryGetLegacyPasswordWithWarning(legacyCredentialStoreName, credentialStoreName) ??
ParameterService.GetParameter<string>(passwordParameterName) ??
PromptForPassword();
}

[CanBeNull]
private static string TryGetLegacyPasswordWithWarning(string legacyName, string newName)
{
var password = TryGetPassword(legacyName);
if (password == null)
return null;

Console.Error.WriteLine(
$"warning FALLOUT003: Found credentials under legacy keychain entry '{legacyName}'. " +
$"Falling back to legacy entry for this run. Re-run `dotnet fallout :secrets` to migrate to '{newName}'. " +
"The legacy entry will no longer be read in 11.0.");
return password;
}

public static string CreateNewPassword(out bool generated)
{
while (true)
Expand Down
Loading
Loading