Skip to content

feat(carvel): emit cross-deployment consumes on runtime config addon job - #666

Merged
drich10 merged 5 commits into
mainfrom
feat/runtime-config-addon-consumes
Jul 28, 2026
Merged

feat(carvel): emit cross-deployment consumes on runtime config addon job#666
drich10 merged 5 commits into
mainfrom
feat/runtime-config-addon-consumes

Conversation

@drich10

@drich10 drich10 commented Jul 21, 2026

Copy link
Copy Markdown
Member

Summary

  • Extends the `job-spec-overlay` sidecar format with two optional fields: `from` and `deployment`
  • When set on a `boshLinkConsumer` entry, `generateRuntimeConfigs()` now includes the link in the `registry-data` addon job's `consumes:` map using the BOSH cross-deployment link resolution schema
  • Extracts a `readJobSpecOverlays()` helper so overlay-reading is shared between `generateBoshReleaseDir()` and `generateRuntimeConfigs()` rather than duplicated

Motivation

Tile authors currently have to post-process the built `.pivotal` to inject a `consumes:` block into the runtime config addon job after `kiln carvel bake`. This change makes it possible to declare cross-deployment link resolution natively in the sidecar files, eliminating the need for that patch step.

Example overlay

consumes:
- name: nats-tls
  type: nats-tls
  optional: false
  from: nats-tls
  deployment: "(( ..cf.deployment_name ))"
- name: binding_cache
  type: binding_cache
  optional: true
  from: binding_cache
  deployment: "(( ..cf.deployment_name ))"

Generated runtime config addon job will include:

consumes:
  nats-tls:
    from: nats-tls
    deployment: (( ..cf.deployment_name ))
  binding_cache:
    from: binding_cache
    deployment: (( ..cf.deployment_name ))

Test plan

  • `go test ./internal/carvel/...` passes (unit + integration tests)
  • New unit tests: `jobSpecOverlay` parses `from`/`deployment` fields correctly, including partial presence (only `from` set, only `deployment` set)
  • Updated integration test: `addon.Jobs[0].Consumes["binding_cache"]` has expected `From`/`Deployment` values in the generated runtime config
  • Entries without `from`/`deployment` are unaffected (no `consumes:` key emitted)

🤖 Generated with Claude Code

Extend job-spec-overlay sidecar format with two optional fields:
  runtime_config_from
  runtime_config_deployment

When set on a boshLinkConsumer entry, generateRuntimeConfigs() now
includes the link in the registry-data addon job's consumes map using
the BOSH cross-deployment link resolution schema (from/deployment).

Also extracts a readJobSpecOverlays() helper to share overlay-reading
between generateBoshReleaseDir() and generateRuntimeConfigs(), avoiding
the need for consumers to post-process the built tile to inject consumes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 21, 2026 17:32
…yment

The runtime_config_ prefix is unnecessary — from and deployment have no
meaning in job.MF, so there is no ambiguity with the existing name/type/optional
fields. The shorter names also mirror the BOSH runtime config schema directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends Carvel tile “job-spec-overlay” sidecars so authors can declare BOSH cross-deployment link resolution for the generated runtime config addon job, and refactors overlay reading into a shared helper.

Changes:

  • Added runtime_config_from / runtime_config_deployment to the *.job-spec-overlay.yml consumes schema and propagate those into the runtime config addon job’s consumes: map.
  • Introduced readJobSpecOverlays() to share sidecar parsing between generateBoshReleaseDir() and generateRuntimeConfigs().
  • Updated unit/integration tests and sample tile testdata to cover parsing + runtime config emission.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
internal/carvel/testdata/sample-tile/packageinstalls/test-install.job-spec-overlay.yml Adds runtime-config cross-deployment fields to the sample overlay consumes entry.
internal/carvel/models/job.go Extends the runtime-config job model to support a consumes map with from/deployment.
internal/carvel/baker.go Adds overlay-reading helper and emits cross-deployment consumes in generated runtime config.
internal/carvel/baker_test.go Adds tests for parsing the new overlay fields and asserting consumes emission in runtime config output.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/carvel/baker.go Outdated
Comment on lines 462 to 468
allConsumes, err := b.readJobSpecOverlays()
if err != nil {
return err
}
deduped := b.deduplicateConsumes(allConsumes)

registryDataSpec, err := buildRegistryDataSpec(registryDataTemplates, registryDataProperties, deduped)
Copilot AI review requested due to automatic review settings July 21, 2026 17:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

internal/carvel/baker.go:321

  • PR description says the sidecar format is extended with runtime_config_from/runtime_config_deployment, but boshLinkConsumer is extended with yaml:"from"/yaml:"deployment". Because buildRegistryDataSpec marshals []boshLinkConsumer directly, any from/deployment values in overlays will also be emitted into the generated registry-data job.MF, not just the runtime config addon job. If the intent is to affect only runtime configs, consider keeping job.MF overlay fields unchanged and adding separate runtime_config_* fields that are consumed only by generateRuntimeConfigs().
// boshLinkConsumer declares a BOSH link the registry-data job should consume.
// Populated from per-packageinstall *.job-spec-overlay.yml sidecar files.
// When From or Deployment is set, kiln also emits a cross-deployment consumes
// entry for the link in the runtime config addon job.
type boshLinkConsumer struct {
	Name       string `yaml:"name"`
	Type       string `yaml:"type"`
	Optional   bool   `yaml:"optional"`
	From       string `yaml:"from,omitempty"`
	Deployment string `yaml:"deployment,omitempty"`
}

Comment thread internal/carvel/baker.go
Comment thread internal/carvel/models/job.go Outdated
Comment on lines +10 to +12
// JobConsumes declares cross-deployment link resolution for a runtime config addon job.
// When a job-spec-overlay declares runtime_config_from or runtime_config_deployment,
// kiln includes this entry in the addon job's consumes map in the generated metadata.
Comment thread internal/carvel/baker.go
Comment on lines +313 to +320
// When From or Deployment is set, kiln also emits a cross-deployment consumes
// entry for the link in the runtime config addon job.
type boshLinkConsumer struct {
Name string `yaml:"name"`
Type string `yaml:"type"`
Optional bool `yaml:"optional"`
Name string `yaml:"name"`
Type string `yaml:"type"`
Optional bool `yaml:"optional"`
From string `yaml:"from,omitempty"`
Deployment string `yaml:"deployment,omitempty"`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think merging is what you want here. Deduping wholesale is reasonable.

Comment on lines +284 to +301
It("parses from and deployment fields for cross-deployment link resolution", func() {
content := `
consumes:
- name: nats-tls
type: nats-tls
optional: false
from: nats-tls
deployment: "(( ..cf.deployment_name ))"
`
var overlay jobSpecOverlay
err := yaml.Unmarshal([]byte(content), &overlay)
Expect(err).NotTo(HaveOccurred())
Expect(overlay.Consumes).To(HaveLen(1))
c := overlay.Consumes[0]
Expect(c.Name).To(Equal("nats-tls"))
Expect(c.From).To(Equal("nats-tls"))
Expect(c.Deployment).To(Equal("(( ..cf.deployment_name ))"))
})
- Fix stale JobConsumes doc comment (was referencing old field names)
- Expand deduplicateConsumes warning to include from/deployment fields
- Add tests for partial field presence (only from set, only deployment set)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 21, 2026 17:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

internal/carvel/baker.go:322

  • Adding from/deployment to boshLinkConsumer means buildRegistryDataSpec() will now serialize those fields into the registry-data job.MF consumes: list (because it YAML-marshals []boshLinkConsumer). BOSH job spec link consumes entries typically only allow name/type/optional, so this can produce an invalid job spec when overlays set these fields. Consider customizing YAML marshalling for boshLinkConsumer (or using a separate type) so job.MF output never includes cross-deployment fields.
	Name       string `yaml:"name"`
	Type       string `yaml:"type"`
	Optional   bool   `yaml:"optional"`
	From       string `yaml:"from,omitempty"`
	Deployment string `yaml:"deployment,omitempty"`

Comment thread internal/carvel/baker_test.go Outdated
Comment on lines +284 to +299
It("emits a consumes entry when only from is set (no deployment)", func() {
content := `
consumes:
- name: nats-tls
type: nats-tls
optional: false
from: nats-tls
`
var overlay jobSpecOverlay
err := yaml.Unmarshal([]byte(content), &overlay)
Expect(err).NotTo(HaveOccurred())
Expect(overlay.Consumes[0].From).To(Equal("nats-tls"))
Expect(overlay.Consumes[0].Deployment).To(BeEmpty())
})

It("emits a consumes entry when only deployment is set (no from)", func() {
@drich10
drich10 marked this pull request as ready for review July 21, 2026 18:17

@rizwanreza rizwanreza left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved.

FWIW, Copilot has some invalid points (i.e. I wouldn't merge duplicates).

- Introduce jobMFConsumes struct to prevent from/deployment fields from
  leaking into the BOSH job.MF spec via buildRegistryDataSpec. The full
  boshLinkConsumer (including from/deployment) is only used internally;
  only name/type/optional are marshaled into job.MF.
- Wrap os.ReadFile error in readJobSpecOverlays with the overlay path for
  consistent diagnostics (matches the existing YAML parse error wrapping).
- Rename two It(...) test descriptions from "emits..." to "parses..." to
  accurately reflect that they test YAML unmarshaling, not output emission.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 21, 2026 19:04

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

The jobMF prefix is overly specific to where the struct is used.
boshConsumes better names what it represents: the BOSH job spec
consumes schema (name/type/optional only).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 21, 2026 19:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

Comment on lines +292 to +296
var overlay jobSpecOverlay
err := yaml.Unmarshal([]byte(content), &overlay)
Expect(err).NotTo(HaveOccurred())
Expect(overlay.Consumes[0].From).To(Equal("nats-tls"))
Expect(overlay.Consumes[0].Deployment).To(BeEmpty())
Comment on lines +307 to +311
var overlay jobSpecOverlay
err := yaml.Unmarshal([]byte(content), &overlay)
Expect(err).NotTo(HaveOccurred())
Expect(overlay.Consumes[0].From).To(BeEmpty())
Expect(overlay.Consumes[0].Deployment).To(Equal("(( ..cf.deployment_name ))"))
Comment thread internal/carvel/baker.go
Comment on lines +760 to +764
consumesMap := make(map[string]models.JobConsumes)
for _, c := range deduped {
if c.From != "" || c.Deployment != "" {
consumesMap[c.Name] = models.JobConsumes{
From: c.From,
@drich10
drich10 merged commit b32665e into main Jul 28, 2026
7 checks passed
@drich10
drich10 deleted the feat/runtime-config-addon-consumes branch July 28, 2026 16:24
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.

3 participants