Skip to content

Conversation

@benbroadaway
Copy link
Collaborator

@benbroadaway benbroadaway commented Jun 20, 2025

Add support for GitHub API authentication via GitHub app installation (versus on-behalf-of user tokens).

New auth input replaces old single accessToken input.

- task: github
  in:
    auth:
      appInstallationSecret:  # preferred, maybe we'll cache it in a future feature
        # secret contains json-formatted appInstallation params
        # { "clientId": "...", "privateKey": "...", "refreshBufferSeconds": 120 }
        org: Default
        name: task-test-auth.json

- task: github
  in:
    auth:
      appInstallation:  # works too
        clientId: "abc12345"
        # pem-encoded app private key generated by github
        privateKey: "${crypto.exportAsString('Default', 'my-private-key', null)"
        refreshBufferSeconds: 120 # optional, 60 is default        

- task: github
  in:
    auth:
      # plain ol' user access token
      accessToken: "${crypto.exportAsString('Default', 'my-token', null)"

- task: github
  in:
    # old way still supported
    accessToken: "${crypto.exportAsString(...)}" 

A public method is added for just generating an access token.

configuration:
  arguments:
    ghParams:
      apiUrl: https://api.github.com
      org: my-org # or username/owner
      repo: my-repo
      auth:
        appInstallationSecret:
          org: Default
          name: task-test-auth.json

flows:
  default:
    - script: myScript.groovy
      in:
        ghToken: "${github.createAppAccessToken(ghParams)}"

App-generate access tokens can be used with the git task.

configuration:
  arguments:
    ghParams:
      apiUrl: https://api.github.com
      org: my-org # or username/owner
      repo: my-repo
      auth:
        appInstallationSecret:
          org: Default
          name: task-test-auth.json

flows:
  testClone:
    - task: git
      in:
        action: "clone"
        url: "https://git.example.com/example-org/git-project.git"
        workingDir: "git-project"
        auth:
          basic:
            username: "username_doesnt_matter"
            password: "${github.createAppAccessToken(ghParams)}"
        baseBranch: "main"
        ignoreErrors: true
      out: response

App-generated access tokens are good for 10 minutes.

@benbroadaway benbroadaway requested review from a team and ibodrov June 20, 2025 22:18
dankle
dankle previously approved these changes Jun 20, 2025

static AccessTokenProvider fromAuth(Auth auth, String baseUrl, String installationRepo, GitSecretService secretService) {

if (auth instanceof Auth.AccessTokenAuth tokenAuth) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think with sealed interfaces we could use switch with pattern matching here?

switch (auth) {
  case Auth.AccessToken -> ...
  case Auth.AppInstallationAuth -> ...
  ...etc
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I had that in mind when first adding the sealed classes...but that's a JDK21 feature. It's preview in JDK17.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah, right. We should move to 21 sometime soon:)

default -> throw new IllegalArgumentException("Unsupported auth type: " + authType.getKey());
};

Auth a = Utils.getObjectMapper().convertValue(authType.getValue(), authClass);
Copy link
Collaborator

Choose a reason for hiding this comment

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

There is private static final ObjectMapper objectMapper already?
Also, GitHubTaskV2 should use @Inject-able ObjectMapper (provided by https://github.com/walmartlabs/concord/blob/master/runtime/v2/runner/src/main/java/com/walmartlabs/concord/runtime/v2/runner/guice/ObjectMapperProvider.java)

Copy link
Collaborator Author

@benbroadaway benbroadaway Jun 26, 2025

Choose a reason for hiding this comment

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

There's definitely too many ObjectMapper's being instantitated. Easy to clean that up.

Regarding injection, easy enough to do for runtime-v2, then throw in a method to whip one up in runtime-v1. However, I have a concern that there's no protection from some other task going ham enabling or disabling features causing side effects. Say, changing timestamp handling, or adding custom deserializers. The should copy it, but it seem pretty easy for accidents to happen.

String token = getString(in, GITHUB_AUTH_ACCESSTOKEN, null);

if (auth.isEmpty()) {
log.warn("Using deprecated 'accessToken' input. Please use 'auth.accessToken.token' instead.");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are there any other properties in auth.accessToken besides .token? Why not just auth.accessToken?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

There is not other expected properties. Treating the auth value as a Map makes it a bit easier to handle it similarly to the other auth types and run it through the same convertValue call and then use with the returned AccessTokenProvider. Otherwise we need more routes of logic handle just a plain ol' String value.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we should prioritize the way it looks in the yml but no strong feelings in this specific case. :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's a fair approach. Addressed in latest commit.

}

@Override
public TaskResult execute(Variables input) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yep yep yep 👍

@ibodrov ibodrov merged commit 0fd2838 into master Sep 8, 2025
1 check passed
@ibodrov ibodrov deleted the github-app-support branch September 8, 2025 13:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

5 participants