Skip to content

refactor: read cookbooks through cinc-api and drop the goruby metadata parser - #265

Merged
tas50 merged 7 commits into
mainfrom
refactor/adopt-cinc-api-cookbook-metadata
Sep 24, 2026
Merged

tas50 merged 7 commits into
mainfrom
refactor/adopt-cinc-api-cookbook-metadata

Conversation

@tas50

@tas50 tas50 commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator

Last of four cinc-api adoption PRs (on v0.15.1). Before this, the CLI had its own metadata.rb parser on top of goruby, three more metadata readers, and three cookbook file walkers. They disagreed with cinc-api and with each other. cinc-api is now the single source of truth for what a cookbook is.

Deleted

  • The goruby-based metadata.rb parser, ReadVersion and its regex, and three separate metadata re-readers. goruby is gone from both modules.
  • Four dead Build*Archive* wrappers, UploadableFromDir, and ExtractArchiveFiles. cli/cookbook/cookbook.go goes from 762 to about 185 lines.
  • The share-tarball walker, the resolver's identifier walker and its second MD5 pass (identifier.go goes from 152 to 32 lines), and the export's cookbook copy.
  • cli/policyfile/extract.go. Four tarball extractors and three "does this path escape" helpers become one cli/internal/tarball. The bundle extractor gains os.Root protection and the ruby.wasm extractor gains size caps.

Behavior changes (each has a test that fails on the old code)

  • supermarket share metadata.json honors privacy true and eager_load_libraries. Before, a private cookbook was shared as not private. A version of 1.2 is sent as 1.2.0, as Chef does. A cookbook's own metadata.json still ships byte for byte.
  • The share tarball follows Chef's loader: .kitchen/, .github/ and .uploaded-cookbook-version.json are left out, and symlinks to files inside the cookbook are included.
  • policy export respects chefignore, leaves out root dot-directories, and follows in-cookbook symlinks, matching the files an upload sends.
  • The resolver reads legacy array-form metadata.json dependencies, and counts in-cookbook symlinks toward the Policyfile identifier. It still matches every golden identifier from a real chef install.
  • Upload and share refuse a metadata.rb that computes its version (it used to upload as 0.0.0) and tell the user how to fix it.
  • Upload from inside an unnamed cookbook uses the directory name. It used to PUT to /cookbooks/./1.0.0.

Test plan

  • go test for ./cli/cookbook/, ./cli/policyfile/... (including the Ruby-backed resolver goldens), ./cli/internal/..., ./apps/cinc/cmd/, ./cli/explore/
  • go vet ./..., gofmt, make docs clean
  • make test-integration (cinc-server-ng): pass

…n parser

cinc-api now reads metadata.rb itself, picks a cookbook's files the way
Chef's loader does, and compiles metadata.json. The CLI carried its own
copy of all three: a goruby-based metadata.rb parser, a regex that read
the version a second time for upload, and a directory walker for the
Supermarket tarball. Drop them and load every local cookbook through
cinc.LocalCookbookFromDir, so upload and share see the same cookbook.

This fixes several things share got wrong:

- the tarball carried root dot-directories (.kitchen, .github) and
  chef-zero's .uploaded-cookbook-version.json, and dropped symlinks to
  files inside the cookbook
- the compiled metadata.json ignored `privacy true` and
  `eager_load_libraries`, so a private cookbook went up as public
- a two-part version ("1.2") went up unnormalized
- a cookbook without a name, shared or uploaded from inside it, was
  named "."

A metadata.rb that computes its version is still refused, now with a
message saying how to fix it. Drops the goruby dependency.

The combined cinc-api branch also changed PushRevision to return a
PushResult; policy deploy reads the revision from it.

Signed-off-by: Tim Smith <tsmith84@proton.me>
…inc-api

The resolver walked cookbooks for their Policyfile identifiers with its
own copy of Chef's loader rules and its own MD5 pass. That copy skipped
every symlink, so a cookbook holding a symlink to one of its own files
got an identifier chef-cli would not compute, and the file set could
drift from what an upload sends. cinc-api's LocalCookbook.Identifiers
covers exactly the files an upload carries; use it. The chef install
goldens still match.

metadata.json is now read with cinc.ParseMetadataJSON, which accepts the
legacy one-element constraint arrays ({"apt": [">= 1.0"]}) older knife
releases wrote. They failed to parse before.

Signed-off-by: Tim Smith <tsmith84@proton.me>
policy export copied each cookbook with a plain directory walk that
ignored chefignore, kept root dot-directories like .kitchen, and dropped
symlinks to files inside the cookbook. The bundle therefore held files
that no upload or push of the same cookbook would carry, and lacked some
it would. Copy the file set cinc-api picks instead, so export, upload and
push agree about what a cookbook is.

The fetch path keeps its plain copy: it caches a source tree as fetched,
and the cookbook rules apply when a cookbook leaves the cache.

Signed-off-by: Tim Smith <tsmith84@proton.me>
Four copies of tar extraction had drifted apart: cli/cookbook and
cli/policyfile duplicated the caps and boundedCopy verbatim, the policy
bundle extractor for push-archive wrote through plain os paths instead of
an os.Root (so a symlink already in the destination could redirect a
write out of it), and the ruby.wasm extractor had no size caps and kept
the archive's file modes. Each also had its own "does this path escape"
helper.

cli/internal/tarball now does it once: os.Root-confined writes, clamped
modes, per-file and per-archive caps, links skipped, and an optional
strip of the top-level directory. Escapes and Within replace the path
helpers. The ruby.wasm tree now extracts with the same clamped modes as
everything else; it only needs to be readable by its owner.

Signed-off-by: Tim Smith <tsmith84@proton.me>
cli/cookbook/CLAUDE.md and cli/policyfile/CLAUDE.md warned that two
walkers decided what a cookbook file is and had to be changed together.
There is now one, in cinc-api, used by upload, share, export, push and
the resolver; point there instead, and at cli/internal/tarball for the
extraction caps.

Signed-off-by: Tim Smith <tsmith84@proton.me>
Signed-off-by: Tim Smith <tsmith84@proton.me>
…rectory

Signed-off-by: Tim Smith <tsmith84@proton.me>
@tas50
tas50 enabled auto-merge (squash) September 24, 2026 10:05
@tas50
tas50 merged commit 9e4516f into main Sep 24, 2026
6 checks passed
@tas50
tas50 deleted the refactor/adopt-cinc-api-cookbook-metadata branch September 24, 2026 10:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant