fix: always write a nuspec into generated NuGet packages - #664
Open
NickJosevski wants to merge 2 commits into
Open
fix: always write a nuspec into generated NuGet packages#664NickJosevski wants to merge 2 commits into
NickJosevski wants to merge 2 commits into
Conversation
The manifest was only generated when the caller supplied a description,
title, release notes or author. Ask for nothing but an ID and a version
and the command still reported success, but produced a .nupkg with no
.nuspec in it: a valid zip, and not a valid NuGet package. Readers
locate the manifest by looking for a single .nuspec in the archive root,
so there was nothing for them to find.
Generate one for every package. The nuspec schema requires description
and authors alongside id and version, so both now default rather than
being filled in only when the caller had already opted into metadata.
The description default is the one the --description flag has always
documented, and the author default is the current user, which is what
the flag's own comment says it should be and what the old Octopus CLI
did. Pass --author to override it.
A base path that already contains {id}.nuspec is left alone and packed
as-is. That file is the user's own: generating over the top would
discard their metadata, and the cleanup step would then delete it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The manifest is assembled by string concatenation, so an ampersand or angle bracket in a description, title or release notes produced a document no XML parser would accept. Release notes in particular are free text, and "fixed A & B" is enough to do it. This was survivable while the nuspec was only written for callers who had opted into metadata. Now that one is generated for every package it is on the path everyone takes, so escape each value on the way in. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Actions #632 (comment), raised by @YuKitsune while reviewing #632. Pre-existing on
main, so it is here rather than there.Problem
package nuget createonly generated the.nuspecwhen the caller supplied a description, title, release notes or author. Ask for nothing but an ID and a version and the command reports success, but the.nupkghas no manifest in it — a valid zip, and not a valid NuGet package:Readers locate the manifest by looking for a single
.nuspecin the archive root, so there is nothing for them to find. #632 makes this sharper:buildOpcPartswrites_rels/.relswith a relationship pointing at/{id}.nuspecunconditionally, so the package also carries a reference to a part that was never created.Change
Generate a manifest for every package:
The schema requires
descriptionandauthorsalongsideidandversion, so both now default instead of being filled in only when the caller had already opted into metadata:descriptionA deployment package created from files on disk.--descriptionhelp promisesauthorsAuthorflag's own comment says it should be, and what the old Octopus CLI didThe author default is the debatable part — it puts a machine username into package metadata for anyone who does not pass
--author. The alternatives were omitting the element (schema-invalid) or a placeholder. Happy to change it. If the user cannot be determined, which happens on minimal container images, the package ID stands in so the command still succeeds.Not clobbering a hand-written nuspec
Generating unconditionally introduced a way to destroy someone's file:
GenerateNuSpecwrites to{basePath}/{id}.nuspecand the caller deletes that path afterwards. Anyone keeping a hand-written manifest in their base path would have had it overwritten and then removed. A supplied nuspec is now detected, packed as-is, and never touched.Second commit: XML escaping
The manifest is assembled by string concatenation, so an ampersand or angle bracket in a description or release notes produced a document no XML parser would accept —
fixed A & Bis enough. Survivable while the nuspec was opt-in; now it is on the path everyone takes.Separate commit (5d04abf) so it can be dropped if you would rather see it on its own.
Verification
15 unit tests in
pkg/cmd/package/nuget/create/create_test.go, asserting against parsed XML rather than substrings. They cover the manifest being generated with no metadata supplied, both defaults, a supplied nuspec being detected, the user-lookup fallback, and escaped values round-tripping.Checked end to end against a built binary: the before/after
unzipoutput above is real, a hand-written nuspec survives byte-identical (diff -qclean) and is the one that gets packed, and the generated file is cleaned up from the base path afterwards.Interaction with #632
Both touch
create.gobut in different places — this one around nuspec generation, #632 around theBuildPackageWithContentscall. Whichever lands second may need a trivial rebase. Once both are in,_rels/.relspoints at a part that always exists.🤖 Generated with Claude Code