Skip to content

Add observability.otlp.ignore-if-missing to downgrade missing OTLP config to warnings#32173

Merged
pelikhan merged 9 commits into
mainfrom
copilot/add-observability-otlp-ignore-if-missing-flag
May 14, 2026
Merged

Add observability.otlp.ignore-if-missing to downgrade missing OTLP config to warnings#32173
pelikhan merged 9 commits into
mainfrom
copilot/add-observability-otlp-ignore-if-missing-flag

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 14, 2026

New Feature

What does this feature do?

This adds an observability.otlp.ignore-if-missing flag so workflows can continue when OTLP endpoint/header secrets resolve to empty values at runtime. Instead of failing gateway startup, gh-aw now logs a warning and skips OTLP gateway config for that run.

Why is this feature needed?

Current behavior is fail-fast when OTLP config is present but runtime values are missing (commonly unset secrets). This makes observability config brittle in shared/imported workflows where telemetry may be optional.

Implementation details

  • Frontmatter + schema support

    • Added observability.otlp.ignore-if-missing to typed frontmatter (OTLPConfig) and JSON schema.
  • Runtime propagation

    • Compiler now emits GH_AW_OTLP_IGNORE_IF_MISSING: true when the flag is enabled.
  • Gateway behavior change

    • start_mcp_gateway.cjs now applies ignore-if-missing semantics:
      • missing/empty OTLP endpoint → warn and remove gateway.opentelemetry block (no hard failure),
      • empty OTLP headers → warn and continue without headers.
  • Docs update

    • Added the new field and injected env var to the frontmatter reference.
observability:
  otlp:
    endpoint: ${{ secrets.OTLP_ENDPOINT }}
    headers:
      Authorization: ${{ secrets.OTLP_TOKEN }}
    ignore-if-missing: true

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title Add observability.otlp.ignore-if-missing warning behavior Add observability.otlp.ignore-if-missing to downgrade missing OTLP config to warnings May 14, 2026
Copilot AI requested a review from pelikhan May 14, 2026 15:51
@pelikhan
Copy link
Copy Markdown
Collaborator

@copilot align ignore-if-missing with other popular actions field names

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 14, 2026

@copilot align ignore-if-missing with other popular actions field names

Updated in 08c78ed: this is now aligned to observability.otlp.if-missing with action-style values (error|warn|ignore), while keeping ignore-if-missing as a deprecated backward-compatible alias.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@pelikhan
Copy link
Copy Markdown
Collaborator

@copilot remove ignore-if-missing support or mention for this feature

Copilot AI and others added 2 commits May 14, 2026 17:31
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 14, 2026

@copilot remove ignore-if-missing support or mention for this feature

Done in b102478 (plus follow-up rename cleanup in b744988). ignore-if-missing support/mentions were removed from frontmatter types, schema, runtime parsing, tests, and docs; only observability.otlp.if-missing remains.

@pelikhan pelikhan marked this pull request as ready for review May 14, 2026 17:43
Copilot AI review requested due to automatic review settings May 14, 2026 17:43
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds opt-in handling for missing/empty OTLP endpoint and header values at workflow runtime. Instead of failing the MCP gateway when OTLP secrets resolve to empty strings, users can set an if-missing mode that lets the gateway proceed without OTLP configuration.

Changes:

  • New observability.otlp.if-missing frontmatter field (string enum: error / warn / ignore) plumbed through types, schema, and docs.
  • Compiler emits GH_AW_OTLP_IF_MISSING: ignore into the workflow env when set to ignore.
  • start_mcp_gateway.cjs reads that env var and strips gateway.opentelemetry (or empty headers) with a warning instead of failing.
Show a summary per file
File Description
pkg/workflow/observability_otlp.go New helpers to read if-missing from parsed and raw frontmatter and inject GH_AW_OTLP_IF_MISSING.
pkg/workflow/observability_otlp_test.go Go tests for the new helper and env-var injection path.
pkg/workflow/frontmatter_types.go Adds IfMissing field to OTLPConfig.
pkg/parser/schemas/main_workflow_schema.json Schema entry with enum error/warn/ignore.
docs/src/content/docs/reference/frontmatter.md Documents the field and new env var.
actions/setup/js/start_mcp_gateway.cjs Runtime: strips OTLP gateway block / empty headers under ignore, switches stdin payload to re-serialized JSON.
actions/setup/js/assign_agent_helpers.cjs Comment-only update to reflect renamed field.

Note: PR description references an older ignore-if-missing: true boolean API and GH_AW_OTLP_IGNORE_IF_MISSING env var, which no longer match the shipped implementation.

Copilot's findings

Tip

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

Comments suppressed due to low confidence (1)

actions/setup/js/start_mcp_gateway.cjs:346

  • The gateway stdin payload was previously the exact bytes read from stdin (mcpConfig); it is now JSON.stringify(configObj), which re-serializes the parsed JSON. This silently strips comments-of-formatting/whitespace, reorders keys to insertion order, and changes any numeric/string representations the gateway might rely on. For typical JSON this is fine, but the change is unconditional — it now happens even when if-missing: ignore is not configured. Consider only re-serializing when applyOTLPIgnoreIfMissing actually mutated configObj, to minimize the blast radius of this change.
  child.stdin.write(JSON.stringify(configObj));
  • Files reviewed: 7/7 changed files
  • Comments generated: 8

Comment on lines +229 to +234
// IfMissing controls runtime behavior when OTLP endpoint/header values are
// missing (for example because a referenced secret is unset). Supported values:
// - "error" (default): fail workflow startup
// - "warn": keep OTLP config and continue (gateway may still fail with invalid OTLP config)
// - "ignore": log a warning and skip OTLP gateway config
IfMissing string `json:"if-missing,omitempty"`
Comment on lines +9334 to +9336
"enum": ["error", "warn", "ignore"],
"default": "error",
"description": "How to handle missing OTLP endpoint/header values at runtime (for example from unset secrets). 'error' fails workflow startup (default), 'warn' continues with OTLP config, and 'ignore' logs a warning and skips OTLP gateway configuration."
Comment on lines +104 to +108
const headers = otelConfig["headers"];
if (typeof headers === "string" && headers.trim() === "") {
delete otelConfig["headers"];
core.info("WARNING: OTLP headers are missing/empty and GH_AW_OTLP_IF_MISSING=ignore; continuing without MCP gateway OTLP headers.");
}
Comment on lines +98 to +103
const endpoint = typeof otelConfig["endpoint"] === "string" ? otelConfig["endpoint"].trim() : "";
if (!endpoint) {
delete gateway["opentelemetry"];
core.info("WARNING: OTLP endpoint is missing/empty and GH_AW_OTLP_IF_MISSING=ignore; skipping MCP gateway OTLP configuration.");
return;
}
Comment thread actions/setup/js/start_mcp_gateway.cjs Outdated
Comment on lines +101 to +107
core.info("WARNING: OTLP endpoint is missing/empty and GH_AW_OTLP_IF_MISSING=ignore; skipping MCP gateway OTLP configuration.");
return;
}
const headers = otelConfig["headers"];
if (typeof headers === "string" && headers.trim() === "") {
delete otelConfig["headers"];
core.info("WARNING: OTLP headers are missing/empty and GH_AW_OTLP_IF_MISSING=ignore; continuing without MCP gateway OTLP headers.");
Comment on lines +84 to +109
function applyOTLPIgnoreIfMissing(configObj) {
if (!isOTLPIfMissingIgnore(process.env.GH_AW_OTLP_IF_MISSING)) {
return;
}
const gw = configObj.gateway;
if (!gw || typeof gw !== "object" || Array.isArray(gw)) {
return;
}
const gateway = /** @type {Record<string, unknown>} */ gw;
const otel = gateway["opentelemetry"];
if (!otel || typeof otel !== "object" || Array.isArray(otel)) {
return;
}
const otelConfig = /** @type {Record<string, unknown>} */ otel;
const endpoint = typeof otelConfig["endpoint"] === "string" ? otelConfig["endpoint"].trim() : "";
if (!endpoint) {
delete gateway["opentelemetry"];
core.info("WARNING: OTLP endpoint is missing/empty and GH_AW_OTLP_IF_MISSING=ignore; skipping MCP gateway OTLP configuration.");
return;
}
const headers = otelConfig["headers"];
if (typeof headers === "string" && headers.trim() === "") {
delete otelConfig["headers"];
core.info("WARNING: OTLP headers are missing/empty and GH_AW_OTLP_IF_MISSING=ignore; continuing without MCP gateway OTLP headers.");
}
}
Comment thread pkg/workflow/observability_otlp.go Outdated
Comment on lines +117 to +148
// getOTLPIgnoreIfMissing returns true when observability.otlp.if-missing is set
// to "ignore".
func getOTLPIgnoreIfMissing(config *FrontmatterConfig, frontmatter map[string]any) bool {
if config != nil && config.Observability != nil && config.Observability.OTLP != nil {
if isOTLPIfMissingIgnore(config.Observability.OTLP.IfMissing) {
return true
}
}
if frontmatter == nil {
return false
}
obsAny, ok := frontmatter["observability"]
if !ok {
return false
}
obsMap, ok := obsAny.(map[string]any)
if !ok {
return false
}
otlpAny, ok := obsMap["otlp"]
if !ok {
return false
}
otlpMap, ok := otlpAny.(map[string]any)
if !ok {
return false
}
if v, ok := otlpMap["if-missing"].(string); ok && isOTLPIfMissingIgnore(v) {
return true
}
return false
}
Comment thread pkg/workflow/observability_otlp.go Outdated
Comment on lines +105 to +115
func isOTLPIfMissingIgnore(mode string) bool {
switch strings.ToLower(strings.TrimSpace(mode)) {
case "ignore":
return true
case "", "error", "warn":
return false
default:
// Unknown values are rejected by schema validation. Keep fail-closed behavior.
return false
}
}
@pelikhan
Copy link
Copy Markdown
Collaborator

@copilot review all comments and all review pull request comments

Copilot AI and others added 4 commits May 14, 2026 18:02
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 14, 2026

@copilot review all comments and all review pull request comments

Done — I reviewed all PR/review comments and addressed the actionable items in commits 620b0d3, 6d7ad07, 74a4828, and 9da4fae.

Key fixes now in the branch include:

  • implemented if-missing: warn runtime behavior,
  • switched warning emission to core.warning,
  • handled empty OTLP headers for string/object/array forms,
  • renamed Go-side mode helper and added invalid-value diagnostics,
  • added JS unit tests for gateway helper behavior,
  • aligned schema/docs text with actual if-missing behavior and scope.

@github-actions
Copy link
Copy Markdown
Contributor

@copilot review all comments — please address the 8 unresolved review threads and post a short summary of the remaining blockers once they are cleared.

Generated by PR Sous Chef ·

@pelikhan pelikhan merged commit ae86bb5 into main May 14, 2026
@pelikhan pelikhan deleted the copilot/add-observability-otlp-ignore-if-missing-flag branch May 14, 2026 19: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.

3 participants