Skip to content

Commit eff20f4

Browse files
committed
Retire CI-059 terminal caller policy
1 parent 75bb0e5 commit eff20f4

31 files changed

Lines changed: 17 additions & 703 deletions

File tree

Sources/GitHub Continuous Integration Validation/GitHub.ContinuousIntegration.Validation.ThinCallers.Job.swift

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@ import GitHub_Standard
44
extension GitHub.ContinuousIntegration.Validation.ThinCallers {
55
/// One top-level job under `jobs:`, with its body lines.
66
///
7-
/// `[CI-059]` is the reason this exists rather than the typed
8-
/// document's `jobs`: the rule needs *same-job co-presence* of a
9-
/// `uses:` and a `secrets:` declaration, and it must still answer on
10-
/// a workflow the parser refuses. So the job set is recovered by the
11-
/// same indentation walk the retired validator used.
7+
/// Job boundaries support diagnostic precedence and the deleted-input
8+
/// check even when the typed parser refuses a malformed caller.
129
public struct Job: Sendable, Equatable {
1310
public let name: String
1411
public let lines: [Line]
@@ -52,29 +49,6 @@ extension GitHub.ContinuousIntegration.Validation.ThinCallers {
5249
}
5350

5451
extension GitHub.ContinuousIntegration.Validation.ThinCallers.Job {
55-
/// The keys of the job's block-form `secrets:` mapping, in order.
56-
///
57-
/// Indentation-tracked: the children are the contiguous run of
58-
/// more-indented `NAME:` lines after a bare `secrets:` opener, and the
59-
/// first line at or below the opener's indent closes the block. Blank
60-
/// and comment lines inside it are skipped rather than ending it.
61-
public var forwardedSecretNames: [String] {
62-
var names: [String] = []
63-
var openerIndent: Int?
64-
for line in lines {
65-
if let indent = openerIndent {
66-
if line.isBlankOrComment { continue }
67-
if line.indent > indent {
68-
if let key = line.mappingKey { names.append(key) }
69-
continue
70-
}
71-
openerIndent = nil
72-
}
73-
if line.isSecretsBlock { openerIndent = line.indent }
74-
}
75-
return names
76-
}
77-
7852
/// The value of `key` inside the job's block-form `with:` mapping, as
7953
/// raw text with any trailing comment removed, or `nil` when `with:`
8054
/// or the key is absent.

Sources/GitHub Continuous Integration Validation/GitHub.ContinuousIntegration.Validation.ThinCallers.Line.swift

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -110,20 +110,6 @@ extension GitHub.ContinuousIntegration.Validation.ThinCallers {
110110
/// `^\s*workflow_call:` — at any indent, including column 0.
111111
var declaresWorkflowCall: Bool { trimmed.hasPrefix("workflow_call:") }
112112

113-
/// `^\s+secrets:\s+inherit\s*(#.*)?$`
114-
var isSecretsInherit: Bool {
115-
guard indent > 0, trimmed.hasPrefix("secrets:") else { return false }
116-
return value(after: "secrets:")?.beforeComment.trimmed == "inherit"
117-
}
118-
119-
/// `^\s+secrets:\s*(#.*)?$` — the block-form opener.
120-
var isSecretsBlock: Bool { indent > 0 && keyWithNoValue == "secrets" }
121-
122-
/// `^\s+secrets:\s*\{` — the inline-map form.
123-
var isSecretsInlineMap: Bool {
124-
indent > 0 && (value(after: "secrets:")?.hasPrefix("{") ?? false)
125-
}
126-
127113
/// The `uses:` target, when the line declares one with a
128114
/// non-empty value.
129115
var usesValue: String? {
@@ -156,27 +142,6 @@ extension GitHub.ContinuousIntegration.Validation.ThinCallers {
156142
return Reference(path: path, ref: ref)
157143
}
158144

159-
/// `^\s+NAME:\s*\$\{\{\s*secrets\.NAME\s*\}\}\s*(#.*)?$` — the
160-
/// exact forwarding line a cross-org caller must carry per name.
161-
func forwards(_ name: String) -> Bool {
162-
guard indent > 0, trimmed.hasPrefix("\(name):"),
163-
let value = value(after: "\(name):")?.beforeComment.trimmed,
164-
value.hasPrefix("${{"), value.hasSuffix("}}")
165-
else { return false }
166-
let inner = value.dropFirst(3).dropLast(2).trimmed
167-
return inner == "secrets.\(name)"
168-
}
169-
170-
/// The `NAME` of a mapping entry, when the line is one.
171-
var mappingKey: String? {
172-
guard let separator = trimmed.firstIndex(of: ":") else { return nil }
173-
let key = String(trimmed[..<separator])
174-
guard !key.isEmpty,
175-
key.allSatisfy({ $0.isLetter || $0.isNumber || $0 == "_" || $0 == "-" })
176-
else { return nil }
177-
return key
178-
}
179-
180145
/// The text after `key`, trimmed. `nil` when the line does not
181146
/// open with it.
182147
func value(after key: String) -> String? {
@@ -203,17 +168,4 @@ extension StringProtocol {
203168
while let last = value.last, last == " " || last == "\t" { value = value.dropLast() }
204169
return String(value)
205170
}
206-
207-
/// Everything before a `#` that opens the string or follows
208-
/// whitespace, which is YAML's own comment rule.
209-
fileprivate var beforeComment: String {
210-
var kept = ""
211-
var previous: Character?
212-
for character in self {
213-
if character == "#", previous == nil || previous == " " || previous == "\t" { break }
214-
kept.append(character)
215-
previous = character
216-
}
217-
return kept
218-
}
219171
}

Sources/GitHub Continuous Integration Validation/GitHub.ContinuousIntegration.Validation.ThinCallers.Message.swift

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -54,63 +54,6 @@ extension GitHub.ContinuousIntegration.Validation.ThinCallers {
5454
"""
5555
}
5656

57-
public static func sameOrganizationExplicit(job: String) -> String {
58-
"""
59-
.github/workflows/ci.yml job `\(job)` invokes an intra-Institute \
60-
reusable with explicit `secrets:` forwarding — per the #92 ruling \
61-
same-org callers MUST use `secrets: inherit`; explicit per-secret \
62-
sets are forbidden. Org-level secrets per [CI-060] obviate explicit \
63-
forwarding, which drifts at every new secret addition.
64-
"""
65-
}
66-
67-
public static func sameOrganizationOmitted(job: String) -> String {
68-
"""
69-
.github/workflows/ci.yml job `\(job)` invokes an intra-Institute \
70-
reusable without `secrets: inherit` — per [CI-059] and the #92 ruling \
71-
every same-org `uses:` invocation of an intra-Institute reusable MUST \
72-
include `secrets: inherit` (single canonical shape per [CI-031], \
73-
universal across consumers regardless of dependency-graph visibility).
74-
"""
75-
}
76-
77-
public static func crossOrganizationInherit(job: String) -> String {
78-
"""
79-
.github/workflows/ci.yml job `\(job)` is sub-org-hosted and uses \
80-
`secrets: inherit` — per the #92 ruling this hop is cross-org and \
81-
inherit silently delivers no org secrets ([CI-109]). Replace with the \
82-
explicit `secrets:` block forwarding \(closedSet) as \
83-
`NAME: ${{ secrets.NAME }}` lines.
84-
"""
85-
}
86-
87-
public static func crossOrganizationMissing(job: String, names: [String]) -> String {
88-
"""
89-
.github/workflows/ci.yml job `\(job)` is sub-org-hosted and \
90-
explicit-forwards secrets but is missing \(names.joined(separator: ", "))\
91-
per the #92 ruling the closed credential set MUST be forwarded in full \
92-
(`NAME: ${{ secrets.NAME }}` per name; [CI-109]).
93-
"""
94-
}
95-
96-
public static func crossOrganizationExtra(job: String, names: [String]) -> String {
97-
"""
98-
.github/workflows/ci.yml job `\(job)` is sub-org-hosted and forwards \
99-
\(names.joined(separator: ", ")) beyond the closed set — per the #92 \
100-
ruling the cross-org transport is exactly \(closedSet); widening it is \
101-
a ruling, not a caller edit.
102-
"""
103-
}
104-
105-
public static func crossOrganizationOmitted(job: String) -> String {
106-
"""
107-
.github/workflows/ci.yml job `\(job)` is sub-org-hosted and invokes an \
108-
intra-Institute reusable without any `secrets:` — per the #92 ruling \
109-
it MUST explicit-forward \(closedSet) ([CI-109]; inherit is \
110-
same-org-only and omission leaves resolve uncredentialed).
111-
"""
112-
}
113-
11457
/// The message deliberately still names `generate-caller.py`, the
11558
/// script this port deletes. Byte-identity with the retired output
11659
/// is the unwaived floor of the single measured comparison, and
@@ -126,11 +69,5 @@ extension GitHub.ContinuousIntegration.Validation.ThinCallers {
12669
Regenerate it with generate-caller.py.
12770
"""
12871
}
129-
130-
static var closedSet: String {
131-
GitHub.ContinuousIntegration.Validation.ThinCallers.crossOrganizationSecrets.joined(
132-
separator: ", "
133-
)
134-
}
13572
}
13673
}

0 commit comments

Comments
 (0)