Skip to content

CI writers emit YAML names via SingleQuote(), which backslash-escapes (invalid YAML for embedded quotes) #483

Description

@avidenic

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/):

  • GitHubActionsArtifactStep.cs:15 — step name:
  • GitHubActionsCacheStep.cs:17 — step name:
  • GitHubActionsCacheStep.cs:27 — the hashFiles('…') key args (GitHub-expression string literals; expression syntax also doubles the quote, so SingleQuoteYaml is correct here too)
  • GitHubActionsRunStep.cs:31 — step name:

Azure Pipelines (src/Fallout.Common/CI/AzurePipelines/Configuration/):

  • AzurePipelinesJob.cs:22displayName:
  • AzurePipelinesJob.cs:29vmImage:⚠️ this calls .SingleQuote().SingleQuote() (quotes twice, unlike AzurePipelinesStage.cs:28 which quotes once). Looks like a pre-existing quirk; check the intended output before converting, don't just swap the method name.
  • AzurePipelinesPublishStep.cs:16displayName:
  • AzurePipelinesPublishStep.cs:20pathToPublish:
  • AzurePipelinesCacheStep.cs:30displayName:
  • AzurePipelinesCmdStep.cs:20displayName:
  • AzurePipelinesStage.cs:21displayName:
  • AzurePipelinesStage.cs:28vmImage:
  • AzurePipelinesDownloadStep.cs:20downloadPath:
  • AzurePipelines.cs:178runTitle pair

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).

Metadata

Metadata

Assignees

Labels

bugSomething isn't workinggood first issueGood for newcomerstarget/vCurrentTargets the current version

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions