Setup GitHub Actions through a GitHub App

2 minute read

In this post I will explain how to setup GitHub Actions programmatically. Although libraries ilke kohsuhke make it easy to commit the workflow files to your repository, the preferred way of authenticating is discouraged for certain use cases. That’s why it might be worth thinking about using a GitHup App instead.

openssl pkcs8 -topk8 -inform PEM -outform DER -in myapp.2021-01-03.private-key.pem -out myapp.2021-01-03.private-key.der -nocrypt

Authentication

  • Generate a Json Web Token
String applicationId = "....";
        
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RS256;

long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);

String keyFile = "....";
byte[] keyBytes = Files.toByteArray(new File(keyFile));

PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
Key signingKey = kf.generatePrivate(spec);

JwtBuilder builder = Jwts.builder()
        .setIssuedAt(now)
        .setIssuer(applicationId)
        .signWith(signingKey, signatureAlgorithm);

// time to live of the token in milliseconds
Long ttlMillis = 60000;
        
long expMillis = nowMillis + ttlMillis;
Date exp = new Date(expMillis);
builder.setExpiration(exp);
 
String jwtToken = builder.compact()
  • Use it to create a so-called App Installation token
GitHub gitHubApp = new GitHubBuilder()
        .withJwtToken(jwtToken)
        .build();

String organisation = "...."
GHAppInstallation appInstallation = gitHubApp
        .getApp()
        .getInstallationByOrganization(organisation);

Map<String, GHPermissionType> permissions = new HashMap<>();
permissions.put("contents", GHPermissionType.WRITE);
permissions.put("metadata", GHPermissionType.READ);

GHAppInstallationToken appInstallationToken = appInstallation
        .createToken(permissions)
        .create();

Don’t worry about the deprecation warnings, as there is no given alternative. This issue describes the background of this problem.

  • Get an installation token, this will authenticate yourself against the organisations auth entity.
GitHub githubAuthAsInst = new GitHubBuilder()
        .withAppInstallationToken(appInstallationToken.getToken())
        .build();

String repositoryName = "...."
var repository  = githubAuthAsInst.getRepository(organisation+"/"+repositoryName);

GitHub Workflow

The final step involves creating a workflow file to describe what should happen in your repository on a commit. As the workflow file is simply a declarative file of workflow actions, we can simply create a file and commit it to the .github directory.

  • Create your workflow file as described in this guide. You can adapt it based on what is needed to build your application.

  • Commit the workflow file to the repository:

String workflowFile = "...."
byte[] workflowFileBytes = Files.asByteSource(new File(workflowFile)).read();
repository.createContent()
        .content(workflowFileBytes)
        .path(".github/workflows/maven.yaml")
        .branch(repository.getDefaultBranch())
        .message("setup workflow file")
        .commit()

Updated: