Problem
StringExtensions.SingleQuote() escapes an embedded single quote with a backslash (\'). That is invalid inside a YAML single-quoted scalar — YAML escapes a quote by doubling it (''). The GitHub Actions and Azure Pipelines writers quote generated names/values through .SingleQuote(), so a value containing an apostrophe emits invalid YAML. It's latent today only because those values are machine-generated from controlled inputs (target names, artifact paths, image ids).
SingleQuoteYaml() — the YAML-correct primitive (doubles the quote) — was added next to SingleQuote() in #475. SingleQuote() must stay as-is for its shell / telemetry / error-message / tool-path / TeamCity callers, where doubling would be wrong.
Outcome
The YAML writers quote via SingleQuoteYaml(). Generated YAML (and GitHub-expression strings) stay valid regardless of the characters in a quoted value.
Call sites to migrate
Reference example already done: GitHubActionsCustomStep.cs quotes its name via Name.SingleQuoteYaml() — copy that pattern.
GitHub Actions (src/Fallout.Common/CI/GitHubActions/Configuration/):
Azure Pipelines (src/Fallout.Common/CI/AzurePipelines/Configuration/):
Leave unchanged (not YAML — doubling would be wrong): the SingleQuote() callers in FalloutBuild.Statics.cs, Execution/ExecutionPlanner.cs, Telemetry/Telemetry.cs, IO/AbsolutePath.cs, Text/String.Quoting.cs, NuGetToolPathResolver.cs, Tools/GitHub/GitHubTasks.cs, Tools/OctoVersion/OctoVersionTasks.cs, and CI/TeamCity/TeamCity.cs (TeamCity service-message format has its own escaping).
Acceptance criteria
- Each YAML/expression call site above uses
SingleQuoteYaml() (or, for AzurePipelinesJob.cs:29, whatever the correct single application is once the double-quote is understood).
- Non-YAML
SingleQuote() callers left unchanged.
- A regression spec with an apostrophe in a generated name for at least one GitHub Actions and one Azure Pipelines writer.
- No snapshot churn on existing controlled-input cases (output is identical when the value contains no quote).
Ref: SingleQuoteYaml in src/Fallout.Utilities/Text/String.Quoting.cs (#475).
Problem
StringExtensions.SingleQuote()escapes an embedded single quote with a backslash (\'). That is invalid inside a YAML single-quoted scalar — YAML escapes a quote by doubling it (''). The GitHub Actions and Azure Pipelines writers quote generated names/values through.SingleQuote(), so a value containing an apostrophe emits invalid YAML. It's latent today only because those values are machine-generated from controlled inputs (target names, artifact paths, image ids).SingleQuoteYaml()— the YAML-correct primitive (doubles the quote) — was added next toSingleQuote()in #475.SingleQuote()must stay as-is for its shell / telemetry / error-message / tool-path / TeamCity callers, where doubling would be wrong.Outcome
The YAML writers quote via
SingleQuoteYaml(). Generated YAML (and GitHub-expression strings) stay valid regardless of the characters in a quoted value.Call sites to migrate
Reference example already done:
GitHubActionsCustomStep.csquotes its name viaName.SingleQuoteYaml()— copy that pattern.GitHub Actions (
src/Fallout.Common/CI/GitHubActions/Configuration/):GitHubActionsArtifactStep.cs:15— stepname:GitHubActionsCacheStep.cs:17— stepname:GitHubActionsCacheStep.cs:27— thehashFiles('…')key args (GitHub-expression string literals; expression syntax also doubles the quote, soSingleQuoteYamlis correct here too)GitHubActionsRunStep.cs:31— stepname:Azure Pipelines (
src/Fallout.Common/CI/AzurePipelines/Configuration/):AzurePipelinesJob.cs:22—displayName:AzurePipelinesJob.cs:29—vmImage:—.SingleQuote().SingleQuote()(quotes twice, unlikeAzurePipelinesStage.cs:28which quotes once). Looks like a pre-existing quirk; check the intended output before converting, don't just swap the method name.AzurePipelinesPublishStep.cs:16—displayName:AzurePipelinesPublishStep.cs:20—pathToPublish:AzurePipelinesCacheStep.cs:30—displayName:AzurePipelinesCmdStep.cs:20—displayName:AzurePipelinesStage.cs:21—displayName:AzurePipelinesStage.cs:28—vmImage:AzurePipelinesDownloadStep.cs:20—downloadPath:AzurePipelines.cs:178—runTitlepairLeave unchanged (not YAML — doubling would be wrong): the
SingleQuote()callers inFalloutBuild.Statics.cs,Execution/ExecutionPlanner.cs,Telemetry/Telemetry.cs,IO/AbsolutePath.cs,Text/String.Quoting.cs,NuGetToolPathResolver.cs,Tools/GitHub/GitHubTasks.cs,Tools/OctoVersion/OctoVersionTasks.cs, andCI/TeamCity/TeamCity.cs(TeamCity service-message format has its own escaping).Acceptance criteria
SingleQuoteYaml()(or, forAzurePipelinesJob.cs:29, whatever the correct single application is once the double-quote is understood).SingleQuote()callers left unchanged.Ref:
SingleQuoteYamlinsrc/Fallout.Utilities/Text/String.Quoting.cs(#475).