@@ -137,7 +137,59 @@ This workflow's own top-level github-app takes precedence over the imported one.
137137 "Current workflow's github-app should take precedence over the imported one" )
138138}
139139
140- // TestTopLevelGitHubAppImportActivation tests that a top-level github-app imported from a shared
140+ // TestTopLevelGitHubAppToolsGitHubTokenSkip tests that the fallback is NOT applied
141+ // to tools.github when a custom github-token is already configured for the MCP server.
142+ func TestTopLevelGitHubAppToolsGitHubTokenSkip (t * testing.T ) {
143+ compiler := NewCompilerWithVersion ("1.0.0" )
144+
145+ // Use ParseWorkflowFile directly with inline frontmatter
146+ tmpDir := t .TempDir ()
147+ workflowsDir := filepath .Join (tmpDir , ".github" , "workflows" )
148+ require .NoError (t , os .MkdirAll (workflowsDir , 0755 ))
149+
150+ // Workflow with top-level github-app but tools.github uses an explicit github-token
151+ workflowContent := `---
152+ on: issues
153+ permissions:
154+ contents: read
155+ github-app:
156+ app-id: ${{ vars.APP_ID }}
157+ private-key: ${{ secrets.APP_PRIVATE_KEY }}
158+ tools:
159+ github:
160+ mode: remote
161+ toolsets: [default]
162+ github-token: ${{ secrets.CUSTOM_PAT }}
163+ engine: copilot
164+ ---
165+
166+ # Workflow With Explicit GitHub Token for MCP
167+
168+ When tools.github.github-token is set, the top-level github-app fallback should NOT override it.
169+ `
170+ mdPath := filepath .Join (workflowsDir , "main.md" )
171+ require .NoError (t , os .WriteFile (mdPath , []byte (workflowContent ), 0644 ))
172+
173+ origDir , err := os .Getwd ()
174+ require .NoError (t , err )
175+ require .NoError (t , os .Chdir (workflowsDir ))
176+ defer func () { _ = os .Chdir (origDir ) }()
177+
178+ data , err := compiler .ParseWorkflowFile ("main.md" )
179+ require .NoError (t , err )
180+
181+ // The top-level github-app should be resolved at the top level
182+ require .NotNil (t , data .TopLevelGitHubApp , "TopLevelGitHubApp should be populated" )
183+
184+ // But it must NOT be injected into tools.github because github-token takes precedence
185+ require .NotNil (t , data .ParsedTools , "ParsedTools should be populated" )
186+ require .NotNil (t , data .ParsedTools .GitHub , "ParsedTools.GitHub should be populated" )
187+ assert .Equal (t , "${{ secrets.CUSTOM_PAT }}" , data .ParsedTools .GitHub .GitHubToken ,
188+ "tools.github.github-token should be preserved" )
189+ assert .Nil (t , data .ParsedTools .GitHub .GitHubApp ,
190+ "tools.github.github-app should NOT be set when github-token is configured" )
191+ }
192+
141193// workflow is propagated to the activation job (reactions/status comments).
142194func TestTopLevelGitHubAppImportActivation (t * testing.T ) {
143195 compiler := NewCompilerWithVersion ("1.0.0" )
0 commit comments