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
3 changes: 2 additions & 1 deletion .fallout/build.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
"RunTargetInDockerImageTest",
"Test",
"UpdateContributors",
"UpdateStargazers"
"UpdateStargazers",
"VerifyGeneratedTools"
]
},
"Verbosity": {
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,5 @@ jobs:
global-json-file: global.json
- name: 'Restore: dotnet tools'
run: dotnet tool restore
- name: 'Run: Test, Pack'
run: dotnet fallout Test Pack
- name: 'Run: VerifyGeneratedTools, Test, Pack'
run: dotnet fallout VerifyGeneratedTools Test Pack
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ dotnet build fallout.slnx
dotnet test tests/Fallout.Common.Tests/Fallout.Common.Tests.csproj
```

Do not commit code generated by `GenerateTools` — generated code is regenerated manually once per release.
Do commit code generated by `GenerateTools` — the `.Generated.cs` files are checked in, and `VerifyGeneratedTools` fails CI if a `.json` spec edit isn't accompanied by regenerating and committing its wrapper.

To restructure an existing PR's commit history into focused commits, use the `/restructure-pr-commits` skill.

Expand Down
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Fallout welcomes contributions. As a community, we want to help each other, prov
- Aim for qualitative, readable code that matches the surrounding style.
- There's no committed `.editorconfig` or ReSharper/`*.DotSettings` file — they were removed during the takeover. Rely on `dotnet format` defaults and review; don't reintroduce them without a maintainer-level decision.
- Add tests when meaningful — every `Foo` project has a sibling `Foo.Tests`.
- Don't commit code generated by `./build.ps1 GenerateTools` — generated `.cs` files are regenerated manually once per release.
- Commit the regenerated `.cs` output alongside the `.json` spec — `VerifyGeneratedTools` fails CI if they drift.
- **Label the PR `target/vCurrent`** for the current release line (use `target/vNext` for work held to next year's major). Legacy `support/v10` maintenance work uses `target/v10`. **Breaking changes are batched to the yearly major cut**: they land on `main` gated behind `[Experimental("FALLOUT0xx")]` (or, when they can't be gated, on a short-lived topic branch off `main`) — never on a `release/YYYY` production train — are held for next year's `YYYY+1.0.0`, and additionally get a `breaking-change` label, a `⚠️ Breaking change` callout, and a `CHANGELOG.md` entry under the next-major `[Unreleased]` heading. Surface that isn't ready to commit to can ship behind `[Experimental("FALLOUT0xx")]` instead of being held back. See the [PR-creation flow](docs/agents/release-and-versioning.md#pr-creation-flow) for the full procedure.

### Tool wrappers
Expand All @@ -70,8 +70,8 @@ Tool wrapper JSON lives under `src/Fallout.Common/Tools/<Tool>/<Tool>.json`. Whe
- `<para/>` between paragraphs (not `<p>...</p>`)
- Don't write `secret: false` (it's the default).
- Don't write `default: xxx` (obsolete).
- Run `./build.ps1 GenerateTools` to verify it generates cleanly.
- Don't commit the generated `.cs` output.
- Run `./build.ps1 GenerateTools` to regenerate the `.cs` output.
- Commit the regenerated `.cs` output alongside the `.json` spec — `VerifyGeneratedTools` fails CI if they drift.

### After opening a PR

Expand Down
2 changes: 1 addition & 1 deletion build/Build.CI.GitHubActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
// protected; all require the ubuntu-latest check.
OnPullRequestBranches = new[] { MainBranch, ReleaseBranchPattern, SupportBranchPattern },
OnPullRequestExcludePaths = new[] { "docs/**", ".assets/**", "**/*.md" },
InvokedTargets = new[] { nameof(ITest.Test), nameof(IPack.Pack) },
InvokedTargets = new[] { nameof(VerifyGeneratedTools), nameof(ITest.Test), nameof(IPack.Pack) },
PublishArtifacts = false)]
[GitHubActions(
"build-cross-platform",
Expand Down
23 changes: 21 additions & 2 deletions build/Build.CodeGeneration.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using Fallout.Common;
using Fallout.Common.IO;
using Fallout.Common.Tools.GitHub;
using Fallout.Common.Utilities.Collections;
using static Fallout.CodeGeneration.CodeGenerator;
using static Fallout.CodeGeneration.ReferenceUpdater;
Expand All @@ -12,6 +11,11 @@ partial class Build
AbsolutePath SpecificationsDirectory => RootDirectory / "src" / "Fallout.Common" / "Tools";
AbsolutePath ReferencesDirectory => RootDirectory / "docs" / "cli-tools";

// Hardcoded rather than derived from the locally-resolved git remote (e.g. via
// GitRepository.Identifier): the generated header comment must stay identical regardless of
// which fork or clone regenerates it, otherwise every regeneration diffs by org name alone.
const string CanonicalRepositoryIdentifier = "Fallout-build/Fallout";

Target References => _ => _
.Requires(() => GitHasCleanWorkingCopy())
.Executes(() =>
Expand All @@ -28,6 +32,21 @@ partial class Build
GenerateCode(
x,
namespaceProvider: x => $"Fallout.Common.Tools.{x.Name}",
sourceFileProvider: x => GitRepository.SetBranch(MainBranch).GetGitHubBrowseUrl(x.SpecificationFile)));
sourceFileProvider: x => $"https://github.com/{CanonicalRepositoryIdentifier}/blob/{MainBranch}/{RootDirectory.GetUnixRelativePathTo(x.SpecificationFile)}"));
});

// CI gate: `GenerateTools` only runs when a contributor remembers to invoke it, so a .json
// spec edited without regenerating its .Generated.cs could merge silently and ship stale
// wrapper code. `Requires` is asserted for the whole scheduled plan before any target runs,
// so the "start clean" check below still fires before GenerateTools regenerates anything;
// the explicit re-check afterward catches drift with a message pointing at the fix.
Target VerifyGeneratedTools => _ => _
.Requires(() => GitHasCleanWorkingCopy())
.DependsOn(GenerateTools)
.Executes(() =>
{
Assert.True(
GitHasCleanWorkingCopy(),
"Generated tool wrappers are out of sync with their .json specs. Run './build.ps1 GenerateTools' locally and commit the result.");
});
}
4 changes: 2 additions & 2 deletions docs/agents/conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,5 @@ When asked to add or extend a tool wrapper:

1. Find the closest existing tool under `src/Fallout.Common/Tools/<Tool>/<Tool>.json`.
2. Copy its shape; cover a full command with all arguments.
3. Run `./build.ps1 GenerateTools` to verify it generates cleanly.
4. Do **not** commit the generated `.cs` output.
3. Run `./build.ps1 GenerateTools` to regenerate the `.cs` output.
4. Commit the regenerated `.cs` output alongside the `.json` spec — `VerifyGeneratedTools` fails CI if they drift.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Generated from https://github.com/ChrisonSimtian/Fallout/blob/main/src/Fallout.Common/Tools/AzureSignTool/AzureSignTool.json
// Generated from https://github.com/Fallout-build/Fallout/blob/main/src/Fallout.Common/Tools/AzureSignTool/AzureSignTool.json

using Fallout.Common;
using Fallout.Common.Tooling;
Expand Down Expand Up @@ -27,7 +27,7 @@ public partial class AzureSignToolTasks : ToolTasks, IRequireNuGetPackage
/// <summary><p>Azure Sign Tool is similar to <c>signtool</c> in the Windows SDK, with the major difference being that it uses Azure Key Vault for performing the signing process. The usage is like <c>signtool</c>, except with a limited set of options for signing and options for authenticating to Azure Key Vault.</p><p>For more details, visit the <a href="https://github.com/vcsjones/AzureSignTool">official website</a>.</p></summary>
public static IReadOnlyCollection<Output> AzureSignTool(ArgumentStringHandler arguments, string workingDirectory = null, IReadOnlyDictionary<string, string> environmentVariables = null, int? timeout = null, bool? logOutput = null, bool? logInvocation = null, Action<OutputType, string> logger = null, Func<IProcess, object> exitHandler = null) => new AzureSignToolTasks().Run(arguments, workingDirectory, environmentVariables, timeout, logOutput, logInvocation, logger, exitHandler);
/// <summary><p>Azure Sign Tool is similar to <c>signtool</c> in the Windows SDK, with the major difference being that it uses Azure Key Vault for performing the signing process. The usage is like <c>signtool</c>, except with a limited set of options for signing and options for authenticating to Azure Key Vault.</p><p>For more details, visit the <a href="https://github.com/vcsjones/AzureSignTool">official website</a>.</p></summary>
/// <remarks><p>This is a <a href="https://github.com/ChrisonSimtian/Fallout">CLI wrapper with fluent API</a> that allows to modify the following arguments:</p><ul><li><c>&lt;files&gt;</c> via <see cref="AzureSignToolSettings.Files"/></li><li><c>--additional-certificates</c> via <see cref="AzureSignToolSettings.AdditionalCertificates"/></li><li><c>--azure-key-vault-accesstoken</c> via <see cref="AzureSignToolSettings.KeyVaultAccessToken"/></li><li><c>--azure-key-vault-certificate</c> via <see cref="AzureSignToolSettings.KeyVaultCertificateName"/></li><li><c>--azure-key-vault-client-id</c> via <see cref="AzureSignToolSettings.KeyVaultClientId"/></li><li><c>--azure-key-vault-client-secret</c> via <see cref="AzureSignToolSettings.KeyVaultClientSecret"/></li><li><c>--azure-key-vault-managed-identity</c> via <see cref="AzureSignToolSettings.KeyVaultManagedIdentity"/></li><li><c>--azure-key-vault-tenant-id</c> via <see cref="AzureSignToolSettings.KeyVaultTenantId"/></li><li><c>--azure-key-vault-url</c> via <see cref="AzureSignToolSettings.KeyVaultUrl"/></li><li><c>--continue-on-error</c> via <see cref="AzureSignToolSettings.ContinueOnError"/></li><li><c>--description</c> via <see cref="AzureSignToolSettings.Description"/></li><li><c>--description-url</c> via <see cref="AzureSignToolSettings.DescriptionUrl"/></li><li><c>--file-digest</c> via <see cref="AzureSignToolSettings.FileDigest"/></li><li><c>--input-file-list</c> via <see cref="AzureSignToolSettings.InputFileList"/></li><li><c>--max-degree-of-parallelism</c> via <see cref="AzureSignToolSettings.MaxDegreeOfParallelism"/></li><li><c>--no-page-hashing</c> via <see cref="AzureSignToolSettings.NoPageHashing"/></li><li><c>--page-hashing</c> via <see cref="AzureSignToolSettings.PageHashing"/></li><li><c>--quiet</c> via <see cref="AzureSignToolSettings.Quiet"/></li><li><c>--skip-signed</c> via <see cref="AzureSignToolSettings.SkipSigned"/></li><li><c>--timestamp-authenticode</c> via <see cref="AzureSignToolSettings.TimestampAuthenticodeUrl"/></li><li><c>--timestamp-digest</c> via <see cref="AzureSignToolSettings.TimestampDigest"/></li><li><c>--timestamp-rfc3161</c> via <see cref="AzureSignToolSettings.TimestampRfc3161Url"/></li><li><c>--verbose</c> via <see cref="AzureSignToolSettings.Verbose"/></li></ul></remarks>
/// <remarks><p>This is a <a href="https://github.com/Fallout-build/Fallout">CLI wrapper with fluent API</a> that allows to modify the following arguments:</p><ul><li><c>&lt;files&gt;</c> via <see cref="AzureSignToolSettings.Files"/></li><li><c>--additional-certificates</c> via <see cref="AzureSignToolSettings.AdditionalCertificates"/></li><li><c>--azure-key-vault-accesstoken</c> via <see cref="AzureSignToolSettings.KeyVaultAccessToken"/></li><li><c>--azure-key-vault-certificate</c> via <see cref="AzureSignToolSettings.KeyVaultCertificateName"/></li><li><c>--azure-key-vault-client-id</c> via <see cref="AzureSignToolSettings.KeyVaultClientId"/></li><li><c>--azure-key-vault-client-secret</c> via <see cref="AzureSignToolSettings.KeyVaultClientSecret"/></li><li><c>--azure-key-vault-managed-identity</c> via <see cref="AzureSignToolSettings.KeyVaultManagedIdentity"/></li><li><c>--azure-key-vault-tenant-id</c> via <see cref="AzureSignToolSettings.KeyVaultTenantId"/></li><li><c>--azure-key-vault-url</c> via <see cref="AzureSignToolSettings.KeyVaultUrl"/></li><li><c>--continue-on-error</c> via <see cref="AzureSignToolSettings.ContinueOnError"/></li><li><c>--description</c> via <see cref="AzureSignToolSettings.Description"/></li><li><c>--description-url</c> via <see cref="AzureSignToolSettings.DescriptionUrl"/></li><li><c>--file-digest</c> via <see cref="AzureSignToolSettings.FileDigest"/></li><li><c>--input-file-list</c> via <see cref="AzureSignToolSettings.InputFileList"/></li><li><c>--max-degree-of-parallelism</c> via <see cref="AzureSignToolSettings.MaxDegreeOfParallelism"/></li><li><c>--no-page-hashing</c> via <see cref="AzureSignToolSettings.NoPageHashing"/></li><li><c>--page-hashing</c> via <see cref="AzureSignToolSettings.PageHashing"/></li><li><c>--quiet</c> via <see cref="AzureSignToolSettings.Quiet"/></li><li><c>--skip-signed</c> via <see cref="AzureSignToolSettings.SkipSigned"/></li><li><c>--timestamp-authenticode</c> via <see cref="AzureSignToolSettings.TimestampAuthenticodeUrl"/></li><li><c>--timestamp-digest</c> via <see cref="AzureSignToolSettings.TimestampDigest"/></li><li><c>--timestamp-rfc3161</c> via <see cref="AzureSignToolSettings.TimestampRfc3161Url"/></li><li><c>--verbose</c> via <see cref="AzureSignToolSettings.Verbose"/></li></ul></remarks>
public static IReadOnlyCollection<Output> AzureSignTool(AzureSignToolSettings options = null) => new AzureSignToolTasks().Run<AzureSignToolSettings>(options);
/// <inheritdoc cref="AzureSignToolTasks.AzureSignTool(Fallout.Common.Tools.AzureSignTool.AzureSignToolSettings)"/>
public static IReadOnlyCollection<Output> AzureSignTool(Configure<AzureSignToolSettings> configurator) => new AzureSignToolTasks().Run<AzureSignToolSettings>(configurator.Invoke(new AzureSignToolSettings()));
Expand Down
Loading
Loading