Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add github-app-auth-only to scala-steward CLI #2973

Open
alexklibisz opened this issue Feb 12, 2023 · 10 comments
Open

Add github-app-auth-only to scala-steward CLI #2973

alexklibisz opened this issue Feb 12, 2023 · 10 comments

Comments

@alexklibisz
Copy link
Contributor

Branching off of this discussion: #2822

I would like to port the github-app-auth-only flag and corresponding behavior from the scala-steward-action directly into scala-steward.

Is there any reason this would be a bad idea?

@alejandrohdezma
Copy link
Member

I think one of the main reasons is because Scala Steward uses the askpass.sh to authenticate with forges (GitHub in this case). So it is something you should provide to Scala Steward from the environment (that's why it was possible to provide it on the action). It shouldn't be too hard though to retrieve an installation token on a Docker environment using the API (here are the docs).

@alexklibisz
Copy link
Contributor Author

IIUC, scala-steward can already take Github app credentials and use them to list all repos available to the app. My thinking was that this change should just restrict that list to the intersection of (all repos available to the app) and (all repos in repos.md).

@alejandrohdezma
Copy link
Member

But in that case the two inputs won't be doing the same thing. Scala-steward doesn't use the provided app/id/secret-key to authenticate GitHub calls (like creating a PR) but just for retrieving the list of repositories available to the App since askpass.sh is used as the source of authentication.

On the other hand the github-app-auth-only input on the action retrieves the installation token for a specific installation and uses that on askpass.sh so PRs (and any call made to the GitHub API) is done using GitHub App credentials.

@alexklibisz
Copy link
Contributor Author

I think I'm starting to understand... It sounds like the Github app ID and key are actually only intended to be an alternative to repos.md. And you still have to provide a token regardless. If that's correct, I think I can probably make a PR to just clarify that in the docs. Right now, that's not obvious at all IMHO.

@alejandrohdezma
Copy link
Member

I think I'm starting to understand... It sounds like the Github app ID and key are actually only intended to be an alternative to repos.md. And you still have to provide a token regardless.

Yeah, that is correct.

If that's correct, I think I can probably make a PR to just clarify that in the docs. Right now, that's not obvious at all IMHO.

That would be more than welcome 😊

@alexklibisz
Copy link
Contributor Author

Help strings are now updated. Thanks for the quick review.

I think it still might make sense to add this --github-app-auth-only flag. Contrary to my initial understanding, the flag would do the following:

  1. Use the app credentials to call the Github API to get a token.
  2. Ignore the repos returned by the app credentials.
  3. Steward the repos in repos.md, using the token returned from step 1 instead of the token returned from git-ask-pass.

@alejandrohdezma
Copy link
Member

I'm not so sure, this is something people could just add to their ask-pass.sh if they want/need the functionality. Having a way to "login" into GitHub different to any other forge could be misleading. @scala-steward-org/core WDYT?

@fthomas
Copy link
Member

fthomas commented Feb 26, 2023

Having a way to "login" into GitHub different to any other forge could be misleading.

I agree with this.

Also, if a GitHub App API token can be retrieved before running Scala Steward in a separate program, that would keep Scala Steward simpler. Maybe it would also make more sense to move the GitHub App code we currently have into a separate program that calls the GitHub App API to create the repos.md that is then consumed by Scala Steward.
All the GitHub App stuff (auth + repos) would then be handled in a separate program that runs before Scala Steward and prepares the askpass program and repos.md.

@alexklibisz
Copy link
Contributor Author

All the GitHub App stuff (auth + repos) would then be handled in a separate program that runs before Scala Steward and prepares the askpass program and repos.md.

I agree that if we don't want to pull more github-specific logic into scala-steward, then the current logic for determining repos from a Github App probably makes more sense to be outside of core scala-steward. Maybe the official action is a good place for it. Whether it's worthwhile to rip it out at this point, is up to you.

I'm happy closing the issue now. I see where you're both coming from, and I think the updated CLI docs should help clarify this for other users.

@fthomas
Copy link
Member

fthomas commented Dec 21, 2023

All the GitHub App stuff (auth + repos) would then be handled in a separate program that runs before Scala Steward and prepares the askpass program and repos.md.

I'm currently experimenting with this idea at https://github.com/scala-steward-org/scala-steward/compare/topic/gh-app-facade. The gist of that GitHub App facade is

private def stewardInstallation(
stewardArgs: List[String],
installation: InstallationOut
): F[Unit] =
for {
jwt <- createJWT
token <- gitHubAppApiAlg.accessToken(jwt, installation.id)
repos <- gitHubAppApiAlg
.repositories(token.token)
.flatMap(_.repositories.traverseFilter(repositoryToRepo))
workspace <- workspaceAlg.rootDir
reposContent = repos.map(r => "- " + r.show).mkString("\n")
reposFile = workspace / s"repos_${installation.id}.md"
_ <- fileAlg.writeFile(reposFile, reposContent)
askPassContent = s"""#!/bin/sh\necho ${token.token}"""
askPassFile = workspace / s"ask-pass-${installation.id}.sh"
_ <- fileAlg.writeFile(askPassFile, askPassContent)
_ <- F.delay(askPassFile.toJava.setExecutable(true))
args = List(
toArg(CoreCli.name.workspace, workspace.pathAsString),
toArg(CoreCli.name.reposFile, reposFile.pathAsString),
toArg(CoreCli.name.gitAskPass, askPassFile.pathAsString),
toArg(CoreCli.name.forgeType, ForgeType.GitHub.asString),
toArg(CoreCli.name.doNotFork)
).flatten ++ stewardArgs
_ <- org.scalasteward.core.Main.runF[F](args).guarantee {
List(reposFile, askPassFile).traverse_(fileAlg.deleteForce)
}
} yield ()
which prepares a repos and askpass file before running Scala Steward for a GH app installation. Since the access token used in an askpass file is specific to an installation, Scala Steward is also able to work with private repositories.

fthomas added a commit that referenced this issue Dec 22, 2023
Prior to this change, the `gitAskPass` program was called once on
start-up and its output was cached and used for API calls to the forge
while Git itself does not cache its output but calls it anytime a password
is needed. This means if the output of `gitAskPass` changes during a Scala
Steward run, the new password is only used for Git operations but not for
forge API calls.

With this change we now do the same as Git and call `gitAskPass`
everytime the password is needed. This should make it easier to support
GitHub Apps proper which require different access tokens during a run.
See also #2973 (comment).
fthomas added a commit that referenced this issue Dec 22, 2023
Prior to this change, the `gitAskPass` program was called once on
start-up and its output was cached and used for API calls to the forge
while Git itself does not cache its output but calls it anytime a password
is needed. This means if the output of `gitAskPass` changes during a Scala
Steward run, the new password is only used for Git operations but not for
forge API calls.

With this change we now do the same as Git and call `gitAskPass`
everytime the password is needed. This should make it easier to support
GitHub Apps proper which require different access tokens during a run.
See also #2973 (comment).
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

No branches or pull requests

3 participants