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
12 changes: 12 additions & 0 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"fallout.globaltool": {
"version": "10.3.37",
"commands": [
"fallout"
]
}
}
}
7 changes: 7 additions & 0 deletions .fallout/build.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@
"Verbosity": {
"description": "Logging verbosity during build execution. Default is 'Normal'",
"$ref": "#/definitions/Verbosity"
},
"BuildProjectFile": {
"type": [
"null",
"string"
],
"description": "Path to the build project (.csproj) relative to the repository root. Defaults to 'build/_build.csproj' when unset. Read by the Fallout global tool's in-tool runner."
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/macos-latest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,11 @@ jobs:
.fallout/temp
~/.nuget/packages
key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj', '**/Directory.Packages.props') }}
- name: 'Setup: .NET SDK'
uses: actions/setup-dotnet@v4
with:
global-json-file: global.json
- name: 'Restore: dotnet tools'
run: dotnet tool restore
- name: 'Run: Test, Pack'
run: ./build.cmd Test Pack
run: dotnet fallout Test Pack
8 changes: 7 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,14 @@ jobs:
.fallout/temp
~/.nuget/packages
key: ${{ runner.os }}-release-${{ hashFiles('**/global.json', '**/*.csproj', '**/Directory.Packages.props', 'version.json') }}
- name: 'Setup: .NET SDK'
uses: actions/setup-dotnet@v4
with:
global-json-file: global.json
- name: 'Restore: dotnet tools'
run: dotnet tool restore
- name: 'Run: Test, Pack, Publish'
run: ./build.cmd Test Pack Publish
run: dotnet fallout Test Pack Publish
env:
# Publish target is nuget.org now that Fallout.* rename has landed (#54).
# NUGET_API_KEY is an API key scoped to push Fallout.* packages, set in
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/ubuntu-latest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,11 @@ jobs:
.fallout/temp
~/.nuget/packages
key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj', '**/Directory.Packages.props') }}
- name: 'Setup: .NET SDK'
uses: actions/setup-dotnet@v4
with:
global-json-file: global.json
- name: 'Restore: dotnet tools'
run: dotnet tool restore
- name: 'Run: Test, Pack'
run: ./build.cmd Test Pack
run: dotnet fallout Test Pack
8 changes: 7 additions & 1 deletion .github/workflows/windows-latest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,11 @@ jobs:
.fallout/temp
~/.nuget/packages
key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj', '**/Directory.Packages.props') }}
- name: 'Setup: .NET SDK'
uses: actions/setup-dotnet@v4
with:
global-json-file: global.json
- name: 'Restore: dotnet tools'
run: dotnet tool restore
- name: 'Run: Test, Pack'
run: ./build.cmd Test Pack
run: dotnet fallout Test Pack
7 changes: 0 additions & 7 deletions build.cmd

This file was deleted.

19 changes: 3 additions & 16 deletions build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
# CONFIGURATION
###########################################################################

$BuildProjectFile = Join-Path $PSScriptRoot 'build/_build.csproj'
$TempDirectory = Join-Path $PSScriptRoot '.fallout/temp'

$DotNetGlobalFile = Join-Path $PSScriptRoot 'global.json'
Expand All @@ -34,36 +33,24 @@ function ExecSafe([scriptblock] $cmd) {
if ($LASTEXITCODE) { exit $LASTEXITCODE }
}

# Print environment variables
# WARNING: Make sure that secrets are actually scrambled in build log
# Get-Item -Path Env:* | Sort-Object -Property Name | ForEach-Object {"{0}={1}" -f $_.Name,$_.Value}

# Check if any dotnet is installed
if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue)) {
ExecSafe { & dotnet --info }
}

# If dotnet CLI is installed globally and it matches requested version, use for execution
# If dotnet CLI is installed globally, use it; otherwise provision a local copy under .fallout\temp.
if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and `
$(dotnet --version) -and $LASTEXITCODE -eq 0) {
$env:DOTNET_EXE = (Get-Command "dotnet").Path
}
else {
# Download install script
$DotNetInstallFile = Join-Path $TempDirectory 'dotnet-install.ps1'
New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
(New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile)

# If global.json exists, load expected version
if (Test-Path $DotNetGlobalFile) {
$DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json)
if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) {
$DotNetVersion = $DotNetGlobal.sdk.version
}
}

# Install by channel or version
$DotNetDirectory = Join-Path $TempDirectory 'dotnet-win'
if (!(Test-Path variable:DotNetVersion)) {
ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath }
Expand All @@ -76,5 +63,5 @@ else {

Write-Output "Microsoft (R) .NET SDK version $(& $env:DOTNET_EXE --version)"

ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary }
ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments }
ExecSafe { & $env:DOTNET_EXE tool restore }
ExecSafe { & $env:DOTNET_EXE fallout $BuildArguments }
19 changes: 3 additions & 16 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
# CONFIGURATION
###########################################################################

BUILD_PROJECT_FILE="$SCRIPT_DIR/build/_build.csproj"
TEMP_DIRECTORY="$SCRIPT_DIR/.fallout/temp"

DOTNET_GLOBAL_FILE="$SCRIPT_DIR/global.json"
Expand All @@ -29,34 +28,22 @@ function FirstJsonValue {
perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}"
}

# Print environment variables
# WARNING: Make sure that secrets are actually scrambled in build log
# env | sort

# Check if any dotnet is installed
if [[ -x "$(command -v dotnet)" ]]; then
dotnet --info
fi

# If dotnet CLI is installed globally and it matches requested version, use for execution
# If dotnet CLI is installed globally, use it; otherwise provision a local copy under .fallout/temp.
if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then
export DOTNET_EXE="$(command -v dotnet)"
else
# Download install script
DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh"
mkdir -p "$TEMP_DIRECTORY"
curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL"
chmod +x "$DOTNET_INSTALL_FILE"

# If global.json exists, load expected version
if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then
DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")")
if [[ "$DOTNET_VERSION" == "" ]]; then
unset DOTNET_VERSION
fi
fi

# Install by channel or version
DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix"
if [[ -z ${DOTNET_VERSION+x} ]]; then
"$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path
Expand All @@ -69,5 +56,5 @@ fi

echo "Microsoft (R) .NET SDK version $("$DOTNET_EXE" --version)"

"$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary
"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@"
"$DOTNET_EXE" tool restore
exec "$DOTNET_EXE" fallout "$@"
9 changes: 7 additions & 2 deletions src/Fallout.Build/CICD/ConfigurationAttributeBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,15 @@ public abstract class ConfigurationAttributeBase : Attribute, IConfigurationGene
public abstract CustomFileWriter CreateWriter(StreamWriter streamWriter);
public abstract ConfigurationEntity GetConfiguration(IReadOnlyCollection<ExecutableTarget> relevantTargets);

// Used by legacy CI providers (AzurePipelines, AppVeyor, TeamCity, SpaceAutomation) that still emit
// ./build.cmd-style step invocations. GitHubActions doesn't read this since v11 — the generator now
// emits a three-step setup-dotnet / tool restore / dotnet fallout shape. Falls back to "build.cmd"
// when no file is found so generators don't throw mid-emit; consumers who removed build.cmd will see
// the broken reference at runtime instead.
protected virtual string BuildCmdPath =>
Build.RootDirectory.GlobFiles("build.cmd", "*/build.cmd")
.Select(x => Build.RootDirectory.GetUnixRelativePathTo(x))
.FirstOrDefault().NotNull("BuildCmdPath != null");
.Select(x => Build.RootDirectory.GetUnixRelativePathTo(x).ToString())
.FirstOrDefault() ?? "build.cmd";

public void Generate(IReadOnlyCollection<ExecutableTarget> executableTargets)
{
Expand Down
10 changes: 10 additions & 0 deletions src/Fallout.Build/Utilities/SchemaUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ private static JsonObject BuildSchema(IFalloutBuild build)
if (userProperties != null)
userSchema["properties"] = userProperties;

// BuildProjectFile is read by the Fallout global tool's in-tool runner from .fallout/parameters.json
// (see Fallout.GlobalTool.BuildProjectResolver). It's not a [Parameter] on the build itself, but we
// surface it in the schema so editors offer IntelliSense when consumers configure a non-conventional
// build project path.
baseProperties["BuildProjectFile"] = new JsonObject
{
["type"] = new JsonArray("null", "string"),
["description"] = "Path to the build project (.csproj) relative to the repository root. Defaults to 'build/_build.csproj' when unset. Read by the Fallout global tool's in-tool runner."
};

// Force the framework parameters Skip/Target to reference the ExecutableTarget definition.
if (baseProperties[InvokedTargetsParameterName] is JsonObject targetProp)
targetProp["items"] = new JsonObject { ["$ref"] = DefinitionsPrefix + "ExecutableTarget" };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,42 @@
// Distributed under the MIT License.
// https://github.com/ChrisonSimtian/Fallout/blob/main/LICENSE

using System;
using System.Collections.Generic;
using System.Linq;
using Fallout.Common.Utilities;
using Fallout.Common.Utilities.Collections;

namespace Fallout.Common.CI.GitHubActions.Configuration;

public class GitHubActionsRunStep : GitHubActionsStep
{
public string BuildCmdPath { get; set; }
public string[] InvokedTargets { get; set; }
public Dictionary<string, string> Imports { get; set; }

public override void Write(CustomFileWriter writer)
{
writer.WriteLine("- name: " + $"Run: {InvokedTargets.JoinCommaSpace()}".SingleQuote());
writer.WriteLine($" run: ./{BuildCmdPath} {InvokedTargets.JoinSpace()}");

if (Imports.Count > 0)
writer.WriteLine("- name: 'Setup: .NET SDK'");
using (writer.Indent())
{
writer.WriteLine("uses: actions/setup-dotnet@v4");
writer.WriteLine("with:");
using (writer.Indent())
{
writer.WriteLine("global-json-file: global.json");
}
}

writer.WriteLine("- name: 'Restore: dotnet tools'");
using (writer.Indent())
{
writer.WriteLine("run: dotnet tool restore");
}

writer.WriteLine("- name: " + $"Run: {InvokedTargets.JoinCommaSpace()}".SingleQuote());
using (writer.Indent())
{
writer.WriteLine($"run: dotnet fallout {InvokedTargets.JoinSpace()}");

if (Imports.Count > 0)
{
writer.WriteLine("env:");
using (writer.Indent())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,6 @@ private IEnumerable<GitHubActionsStep> GetSteps(GitHubActionsImage image, IReadO

yield return new GitHubActionsRunStep
{
BuildCmdPath = BuildCmdPath,
InvokedTargets = InvokedTargets,
Imports = GetImports().ToDictionary(x => x.Key, x => x.Value)
};
Expand Down
27 changes: 18 additions & 9 deletions src/Fallout.GlobalTool/Program.Setup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -195,19 +195,13 @@ private static void WriteBuildScripts(
AbsolutePath buildDirectory,
string buildProjectName)
{
(scriptDirectory / "build.cmd").WriteAllLines(
FillTemplate(GetTemplate("build.cmd")),
platformFamily: PlatformFamily.Linux);

(scriptDirectory / "build.sh").WriteAllLines(
FillTemplate(
GetTemplate("build.sh"),
tokens: GetDictionary(
new
{
RootDirectory = scriptDirectory.GetUnixRelativePathTo(rootDirectory),
BuildDirectory = scriptDirectory.GetUnixRelativePathTo(buildDirectory),
BuildProjectName = buildProjectName,
})),
platformFamily: PlatformFamily.Linux);

Expand All @@ -218,12 +212,27 @@ private static void WriteBuildScripts(
new
{
RootDirectory = scriptDirectory.GetWinRelativePathTo(rootDirectory),
BuildDirectory = scriptDirectory.GetWinRelativePathTo(buildDirectory),
BuildProjectName = buildProjectName,
})),
platformFamily: PlatformFamily.Windows);

MakeExecutable(scriptDirectory / "build.cmd");
// .config/dotnet-tools.json pins Fallout.GlobalTool as a local tool so the thin shims
// (build.sh / build.ps1) can `dotnet tool restore` and `dotnet fallout` deterministically.
// Skip if the consumer already has a manifest — they may have other tools pinned and we
// don't want to clobber. They can add the `fallout.globaltool` entry manually.
var toolManifest = rootDirectory / ".config" / "dotnet-tools.json";
if (!toolManifest.FileExists())
{
(rootDirectory / ".config").CreateDirectory();
toolManifest.WriteAllLines(
FillTemplate(
GetTemplate("dotnet-tools.json"),
tokens: GetDictionary(
new
{
FalloutGlobalToolVersion = typeof(Program).GetTypeInfo().Assembly.GetVersionText(),
})));
}

MakeExecutable(scriptDirectory / "build.sh");

void MakeExecutable(AbsolutePath scriptFile)
Expand Down
7 changes: 0 additions & 7 deletions src/Fallout.GlobalTool/templates/build.cmd

This file was deleted.

15 changes: 3 additions & 12 deletions src/Fallout.GlobalTool/templates/build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
# CONFIGURATION
###########################################################################

$BuildProjectFile = Join-Path $PSScriptRoot '_BUILD_DIRECTORY_/_BUILD_PROJECT_NAME_.csproj'
$TempDirectory = Join-Path $PSScriptRoot '_ROOT_DIRECTORY_/.fallout/temp'

$DotNetGlobalFile = Join-Path $PSScriptRoot '_ROOT_DIRECTORY_/global.json'
Expand All @@ -32,27 +31,24 @@ function ExecSafe([scriptblock] $cmd) {
if ($LASTEXITCODE) { exit $LASTEXITCODE }
}

# If dotnet CLI is installed globally and it matches requested version, use for execution
# If dotnet CLI is installed globally, use it; otherwise provision a local copy under .fallout\temp.
if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and `
$(dotnet --version) -and $LASTEXITCODE -eq 0) {
$env:DOTNET_EXE = (Get-Command "dotnet").Path
}
else {
# Download install script
$DotNetInstallFile = Join-Path $TempDirectory 'dotnet-install.ps1'
New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
(New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile)

# If global.json exists, load expected version
if (Test-Path $DotNetGlobalFile) {
$DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json)
if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) {
$DotNetVersion = $DotNetGlobal.sdk.version
}
}

# Install by channel or version
$DotNetDirectory = Join-Path $TempDirectory 'dotnet-win'
if (!(Test-Path variable:DotNetVersion)) {
ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath }
Expand All @@ -65,10 +61,5 @@ else {

Write-Output "Microsoft (R) .NET SDK version $(& $env:DOTNET_EXE --version)"

if (Test-Path env:NUKE_ENTERPRISE_TOKEN) {
& $env:DOTNET_EXE nuget remove source "nuke-enterprise" > $null
& $env:DOTNET_EXE nuget add source "https://f.feedz.io/nuke/enterprise/nuget" --name "nuke-enterprise" --username "PAT" --password $env:NUKE_ENTERPRISE_TOKEN > $null
}

ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet }
ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments }
ExecSafe { & $env:DOTNET_EXE tool restore }
ExecSafe { & $env:DOTNET_EXE fallout $BuildArguments }
Loading
Loading