Skip to content

Fix visibility for organization and enterprise variable creation - #56267

Open
pelikhan with Copilot wants to merge 5 commits into
mainfrom
copilot/gh-aw-env-update-fix
Open

Fix visibility for organization and enterprise variable creation#56267
pelikhan with Copilot wants to merge 5 commits into
mainfrom
copilot/gh-aw-env-update-fix

Conversation

Copilot AI commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

gh aw env update could update existing organization and enterprise variables but failed to create them because POST requests omitted the required visibility field.

  • CLI behavior

    • Add --visibility all|private|selected, defaulting to all.
    • Reject unsupported values and repo-scope usage with actionable errors.
  • Variable creation

    • Include visibility on organization and enterprise POST requests.
    • Keep repo POST and all PATCH requests unchanged, preserving existing visibility during updates.
    • Provide targeted guidance for visibility-related API failures without masking unrelated errors.
  • Documentation

    • Document create-only visibility behavior and selected-repository handling.
    • Update enterprise examples and the changelog.
gh aw env update defaults.yml \
  --scope org \
  --org MY_ORG \
  --visibility all

Copilot AI and others added 2 commits August 27, 2026 06:46
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix missing visibility in gh aw env update for org variables Fix visibility for organization and enterprise variable creation Aug 27, 2026
Copilot AI requested a review from pelikhan August 27, 2026 07:06
@pelikhan
pelikhan marked this pull request as ready for review August 27, 2026 07:08
Copilot AI balanced review requested due to automatic review settings August 27, 2026 07:08
@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ failed during design decision gate check.

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel skipped because pre-fetch PR data was unavailable: unable to fetch test file diff

🧪 Test quality analysis by Test Quality Sentinel

@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Ponytail Reviewer completed successfully!

Lean already. Ship.

Generated by Ponytail Reviewer for #56267

@github-actions

Copy link
Copy Markdown
Contributor

Comment Memory

reviewed_at: 2026-08-27T07:10:00Z
review_event: COMMENT
top_themes:
  - no actionable blocking issues found in changed lines
  - visibility flag validation and create-path coverage look adequate
files_reviewed:
  - CHANGELOG.md
  - docs/src/content/docs/reference/compiler-enterprise-environment-controls.md
  - docs/src/content/docs/reference/governance.md
  - pkg/cli/env_command.go
  - pkg/cli/env_command_test.go
comment_count: 0

Note

This comment is managed by comment memory.

It stores persistent context for this thread in the code block at the top of this comment.
Edit only the text inside the backtick fences; workflow metadata and the footer are regenerated automatically.

Learn more about comment memory

🔎 Code quality review by PR Code Quality Reviewer · pi · gpt54 · 7.49 AIC · ⌖ 6.86 AIC · ⊞ 7K ·
Comment /review to run again

@github-actions github-actions Bot 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.

Verdict

Non-blocking from a code-quality standpoint.

Why I'm not blocking this This change fixes the missing visibility on org/enterprise variable creation, keeps PATCH behavior unchanged so existing visibility is preserved, and adds focused tests around both argument construction and error handling. I did not find a correctness or maintainability issue in the changed lines that is strong enough to block merge.

🔎 Code quality review by PR Code Quality Reviewer · pi · gpt54 · 7.49 AIC · ⌖ 6.86 AIC · ⊞ 7K
Comment /review to run again

@github-actions github-actions Bot 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.

Review: Fix visibility for organization and enterprise variable creation

This is a clean, well-scoped bug fix. The changes correctly thread a --visibility flag through validation → target resolution → API call for org/ent scopes, and the test coverage is thorough (argument presence, PATCH-first semantics, error branches, flag validation).

One non-blocking concern (harden): The visibility-specific error hint in upsertDefaultsVariable uses a fragile string search on the raw API response (strings.Contains(strings.ToLower(string(out)), "visibility")). If the API error message ever changes wording, or if an unrelated field named "visibility" appears in a different error, the hint could silently disappear or appear spuriously. Since the visibility parameter is always mandatory for org/ent creates, surfacing the hint unconditionally for all create failures at those scopes would be simpler and more robust — see the inline comment for details.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · copilot · sonnet46 · 26.8 AIC · ⌖ 9.21 AIC · ⊞ 6.2K

Comment thread pkg/cli/env_command.go
if (target.scope == defaultsScopeOrg || target.scope == defaultsScopeEnt) &&
strings.Contains(strings.ToLower(string(out)), "visibility") {
scopeName := "organization"
example := "gh aw env update defaults.yml --scope org --org my-org --visibility all"

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.

The visibility-specific error branch relies on a string search for "visibility" in the raw API response body:

strings.Contains(strings.ToLower(string(out)), "visibility")

This is a brittle heuristic — any API error that incidentally mentions "visibility" (e.g. an unrelated 422 about a different field, or a future error message that changes wording) would trigger the misleading "variables require a visibility" hint even when the real failure is a permissions error, bad slug, or quota issue.

Consider always including the visibility hint for all create failures at org/ent scope, since it is always valid context:

if target.scope == defaultsScopeOrg || target.scope == defaultsScopeEnt {
    // always surface the visibility hint for create failures
}

This makes the message both more reliable and more helpful without risking false negatives if the API response wording changes. @copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Kept the guidance limited to the actual HTTP 422 missing-visibility response so policy and permission failures retain their original error context. The classifier and tests now cover this distinction in pkg/cli/env_command.go.

@github-actions github-actions Bot 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.

Skills-Based Review 🧠

Applied /diagnosing-bugs — requesting changes on two issues in upsertDefaultsVariable.

📋 Key Themes & Highlights

Key Themes

  • Fragile post-fix heuristic: The strings.Contains(..., "visibility") error branch (line 580) is likely dead code now that visibility is always sent, and it can false-positive on unrelated API errors.
  • Error construction style: console.FormatErrorMessage is called at error construction time (line 588) rather than at display time, breaking the error-chain pattern used everywhere else in this file.

Positive Highlights

  • ✅ Root cause properly fixed — visibility is now sent unconditionally on POST for org/ent scope
  • ✅ Excellent test coverage: new tests cover PATCH→POST fallback, existing-variable preservation, visibility error, and unrelated error paths
  • validateDefaultsVisibility is cleanly separated and independently tested
  • ✅ PATCH path correctly left unchanged — existing variables preserve their visibility
  • ✅ Documentation and changelog updated consistently

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet46 · 30.5 AIC · ⌖ 10.1 AIC · ⊞ 7.6K
Comment /matt to run again

Comment thread pkg/cli/env_command.go Outdated
if err != nil {
return fmt.Errorf("failed to set %s: %w", name, errWithOutput(err, out))
if (target.scope == defaultsScopeOrg || target.scope == defaultsScopeEnt) &&
strings.Contains(strings.ToLower(string(out)), "visibility") {

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.

[/diagnosing-bugs] The visibility-error heuristic is fragile and likely dead code after this fix. Because visibility is now unconditionally sent in the POST body (line 575), the API should never respond with a "visibility missing" error. If it does fire, any API error whose response body happens to mention "visibility" for an unrelated reason (e.g. "invalid visibility value") will show the misleading "variables require a visibility" hint even though the user already supplied one.

💡 Suggested approach

Since visibility is always sent now, remove the strings.Contains(..., "visibility") special-case entirely and simplify to:

return fmt.Errorf("failed to create %s at %s scope: %w", name, target.scope, errWithOutput(err, out))

Add a test case where the POST fails with a non-visibility error (e.g. HTTP 403) to confirm the plain error message is surfaced without noise.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The special case now applies only to HTTP 422 missing-visibility responses; unrelated create failures use the plain error wrapper. Added coverage for an invalid visibility response in 91b6e04.

Comment thread pkg/cli/env_command.go Outdated
example = "gh aw env update defaults.yml --scope ent --enterprise my-ent --visibility all"
}
message := fmt.Sprintf("failed to create %s at %s scope: %s variables require a visibility. Expected one of all, private, selected. Example: %s", name, target.scope, scopeName, example)
return fmt.Errorf("%s: %w", console.FormatErrorMessage(message), errWithOutput(err, out))

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.

[/diagnosing-bugs] Double-wrapping console.FormatErrorMessage inside fmt.Errorf with %w leaks styled/formatted markup into the error chain. When this error is unwrapped or displayed in a non-terminal context (logs, test output), the caller sees both the styled prefix and the raw errWithOutput tail, which looks inconsistent. Compare with line 590, which formats cleanly without FormatErrorMessage.

💡 Suggested fix

Either format only the message without %w, or (better) separate the user-facing message from the wrapped error, consistent with the pattern on line 590:

// cleaner — consistent with line 590
return fmt.Errorf("%s: %w", message, errWithOutput(err, out))
// where `message` is the plain string (no FormatErrorMessage wrapping)

If styled output is required here, apply FormatErrorMessage only at the point the error is displayed to the user, not when it is constructed.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed console.FormatErrorMessage from the wrapped error in 91b6e04, leaving a plain message and the underlying command error.

@github-actions

Copy link
Copy Markdown
Contributor

Test Quality Sentinel 🧪

PR: #56267 — Fix visibility for organization and enterprise variable creation

Summary

Score: 80/100 (Excellent)

1 new test added, 1 design-contract test, 1 edge-case scenario covered. Test verifies the critical fix: unrelated errors (e.g., HTTP 403) no longer trigger visibility-requirement messaging.

Test Metrics

Metric Value
New tests 1
Design tests 1/1 (100%)
Edge-case coverage 1/1 (100%)
Assertions 3
Hard violations 0
Build tags ✅ Present
Mock libraries (gomock) None

Test Analysis

TestUpsertDefaultsVariableCreateUnrelatedError — Design test, high value

Purpose: Validates error messaging when variable creation fails with an unrelated error (HTTP 403 Forbidden). The fix ensures visibility-related guidance only appears when visibility is actually the issue.

Assertions:

  • require.Error(t, err) — Error is raised ✅
  • assert.Contains(err.Error(), "failed to create GH_AW_DEFAULT_MAX_TURNS at org scope") — Correct error prefix ✅
  • assert.NotContains(err.Error(), "variables require a visibility") — Does NOT suggest visibility for unrelated errors ✅
  • assert.Contains(err.Error(), "HTTP 403: Forbidden") — Original error preserved ✅

Design contract: When an org/enterprise variable creation fails with a non-visibility error, the error message MUST NOT include visibility guidance.

Regression value: HIGH — Without this test, a future change could accidentally re-introduce the false visibility suggestion for all errors.

Flags

⚠️ Test inflation ratio: 5.3:1 (16 test lines added vs 3 production lines changed)

While the test quality is high (comprehensive edge-case coverage), the length-to-production-change ratio exceeds the 2:1 threshold. This is not wasteful — the test is properly structured and validates a critical error path — but noted for visibility.

Approval

✅ No hard violations (build tags present, no mock library usage, all assertions descriptive). Test covers behavioral contract with appropriate edge-case scenario.


🧪 Test quality analysis by Test Quality Sentinel · copilot · haiku45 · 32.9 AIC · ⌖ 6.21 AIC · ⊞ 8.3K ·
Comment /review to run again

@github-actions github-actions Bot 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.

✅ Test Quality Sentinel: 80/100. Design test with comprehensive edge-case coverage. Build tags present, no mock library violations, all assertions descriptive.

Copilot AI 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.

Pull request overview

Fixes organization and enterprise variable creation by supplying visibility while preserving existing visibility during updates.

Changes:

  • Adds and validates --visibility.
  • Sends visibility only on organization/enterprise POST requests.
  • Adds tests and documentation.
Show a summary per file
File Description
pkg/cli/env_command.go Implements visibility handling and API errors.
pkg/cli/env_command_test.go Tests visibility validation and requests.
docs/src/content/docs/reference/governance.md Documents visibility behavior.
docs/src/content/docs/reference/compiler-enterprise-environment-controls.md Adds usage examples.
CHANGELOG.md Records the fix.

Review details

  • Files reviewed: 5/5 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment on lines +304 to +308
if tt.expectedVisibility == "" {
assert.NotContains(t, calls[1], "visibility=")
} else {
assert.Contains(t, calls[1], tt.expectedVisibility)
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated the repository-create assertion to reject any argument with the visibility= prefix in 91b6e04.

Comment thread pkg/cli/env_command.go Outdated
Comment on lines +579 to +580
if (target.scope == defaultsScopeOrg || target.scope == defaultsScopeEnt) &&
strings.Contains(strings.ToLower(string(out)), "visibility") {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Restricted the hint to HTTP 422 missing-field signatures and added a test showing an invalid visibility response retains the generic error in 91b6e04.

@github-actions

Copy link
Copy Markdown
Contributor

Category: bug | Risk: high | Score: 70 (impact 36 + urgency 22 + quality 12) | Action: fast_track | Batch: permissions-security | Note: Variable creation fix with enterprise/org behavior change.

Generated by 🔧 PR Triage Agent · copilot · mai10 · 17.8 AIC · ⌖ 2.49 AIC · ⊞ 16.6K ·

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gh aw env update --scope org cannot create variables that do not already exist (HTTP 422: missing visibility)

3 participants