Skip to content

Pass shared build config via artifact to eliminate duplicate inputs#37

Draft
reakaleek wants to merge 6 commits intomainfrom
pepper-character
Draft

Pass shared build config via artifact to eliminate duplicate inputs#37
reakaleek wants to merge 6 commits intomainfrom
pepper-character

Conversation

@reakaleek
Copy link
Copy Markdown
Member

Summary

Consumer repos must currently specify the same 5 inputs (strict, continue-on-error, path-pattern, path-pattern-ignore, enable-vale-linting) in both their docs-build.yml and docs-deploy.yml caller workflows. For example, docs-content and docs-eng-playground both duplicate enable-vale-linting: true and path-pattern: 'docs/**' across both files. This creates maintenance burden and drift risk when the values diverge between the two callers.

How it works

  1. docs-build.yml — new export-config job serializes the 5 shared input values into a versioned JSON artifact (docs-build-config) using jq --arg
  2. docs-deploy.yml — downloads the artifact from the triggering workflow_run, validates it, and uses the values via preflight job outputs (cfg-strict, cfg-continue-on-error, etc.)
  3. The 5 shared inputs are removed from docs-deploy.yml's workflow_call interface — only disable-comments and enable-cumulative-comment remain
  4. If no artifact is found (e.g. older build workflow version), hardcoded defaults are emitted matching the previous input defaults

Security hardening

The artifact is parsed defensively since it originates from a different workflow run:

  • No shell interpolation: JSON produced with jq --arg, parsed exclusively with jq
  • Schema validation: version field, type checks on every field
  • Value allowlisting: strict and continue-on-error must be exactly "true" or "false"
  • Character denylisting: path patterns reject shell metacharacters (;|&$\(){}\`)
  • Artifact pinning: downloaded with explicit run-id: ${{ github.event.workflow_run.id }}
  • Heredoc output: path values written to $GITHUB_OUTPUT using heredoc delimiters to prevent multi-line corruption

Breaking change

Consumer repos that pass the 5 removed inputs to docs-deploy.yml will get a workflow validation error and must remove them from their deploy caller workflow. After this change, a consumer's docs-deploy.yml simplifies from:

# Before
jobs:
  deploy:
    uses: elastic/docs-actions/.github/workflows/docs-deploy.yml@v1
    with:
      path-pattern: 'docs/**'
      enable-vale-linting: true

to:

# After
jobs:
  deploy:
    uses: elastic/docs-actions/.github/workflows/docs-deploy.yml@v1

The shared config values are now automatically inherited from whatever was passed to docs-build.yml.

Test plan

  • Point a consumer repo (e.g. docs-eng-playground) at this branch for both workflows
  • Verify docs-build-config artifact is uploaded by the build workflow
  • Verify docs-deploy downloads and parses the artifact (check "Parse and validate config" step logs)
  • Verify build + deploy succeed with artifact-sourced values
  • Verify backward compat: temporarily remove artifact upload to confirm deploy falls back to defaults
  • Verify invalid JSON / bad schema in artifact causes a hard failure (not silent fallback)

🤖 Generated with Claude Code

reakaleek and others added 6 commits March 26, 2026 13:59
Consumer repos currently must specify the same inputs (strict,
continue-on-error, path-pattern, path-pattern-ignore, enable-vale-linting)
in both their docs-build and docs-deploy caller workflows. This creates
maintenance burden and drift risk when the values diverge.

docs-build.yml now exports these shared inputs as a versioned JSON
artifact (docs-build-config). docs-deploy.yml downloads it from the
triggering workflow_run and uses those values, removing the 5 duplicate
inputs from its workflow_call interface.

Security: JSON is produced with jq --arg (no shell interpolation),
parsed with jq only, schema/type-validated, boolean values allowlisted,
and path patterns denied shell metacharacters. The artifact is tied to
the specific workflow_run.id.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Instead of manually serializing each shared input field, use
toJSON(inputs) to pass the entire inputs object as a single JSON
blob. The deploy workflow uses fromJSON() to access individual
fields. Adding new shared inputs now requires zero changes to the
serialization/deserialization code.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The version field added speculative complexity without a concrete use
case. The artifact now contains the raw toJSON(inputs) output, and the
deploy side reads it directly with no unwrapping.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The deploy workflow now requires the config artifact from the build
workflow. If it is missing, the download step fails hard rather than
falling back to defaults silently.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
toJSON(inputs) is produced by GitHub from schema-constrained
workflow_call inputs — the JSON is always valid and values are
always scalars. No need to re-validate on the deploy side.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
It defaults to github.token already.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@reakaleek reakaleek added the enhancement New feature or request label Mar 26, 2026
@reakaleek reakaleek marked this pull request as draft March 26, 2026 13:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant