Create your first GitHub Action

Create a repository

GitHub Actions have to be hosted in a GitHub repository that is dedicated to the action.

Thus the first step in the creation of a GitHub Action is to create a new GitHub repository. Create a completely empty repository (e.g. no README nor .gitignore nor license file), that will make the next steps easier. You can add them later on.

Do not initialize or clone the repository. We will initialize a local Git repository and push it to GitHub in the following steps.

The full name of your repository (either username/repository-name or org-name/repository-name) is going to be useful in the next step so keep it handy. In the following sections, we will consider it named my/action-github-repository.

If you created a private repository to host your action, make your action visible to your other private repositories by following these instructions.

Note that actions stored in private repositories are not runnable in public repositories.

Initialize your Quarkus application

A Quarkus GitHub Action is a standard Quarkus application.

You can create one including the Quarkus GitHub Action extension using the following Quarkus CLI command:

Make sure you use the 📋 button to copy the command.
quarkus create app \
    -x quarkus-github-action \ (1)
    org.acme:my-github-action:999-SNAPSHOT \ (2)
    --name="My Action" \ (3)
    --description="Description of my action" \ (4)
    --data=quarkiverse-github-action-codestart.github-repository=my/action-github-repository (5)
1 The Quarkus GitHub Action extension. Add it right away so that the tooling can generate a full Quarkus GitHub Action application using Codestarts.
2 The GAV of your Maven project.
3 The name of the action. It is used both in the pom.xml and in the descriptor of the action (action.yml).
4 The description of the action. It is used both in the pom.xml and in the descriptor of the action (action.yml).
5 The full name of the GitHub repository hosting the action (in the form username/repository-name or org-name/repository-name).

On Windows and macOS, it is recommended to concatenate all the options on one line (without \), as the \ might not be correctly interpreted.

We highly recommend the usage of the Quarkus CLI but if you cannot install it or prefer using Maven, you can create a Quarkus GitHub Action project using the following Maven command:

Make sure you use the 📋 button to copy the command.
mvn io.quarkus.platform:quarkus-maven-plugin:3.13.2:create \
    -DplatformVersion=3.13.2 \
    -DprojectGroupId=org.acme \ (1)
    -DprojectArtifactId=my-github-action \ (2)
    -DprojectVersion=999-SNAPSHOT \ (3)
    -DprojectName="My Action" \ (4)
    -DprojectDescription="Description of my action" \ (5)
    -Ddata="quarkiverse-github-action-codestart.github-repository=my/action-github-repository" \ (6)
    -Dextensions="quarkus-github-action" (7)
1 The groupId of your Maven project.
2 The artifactId of your Maven project.
3 The version of your Maven project. Let’s make it a rolling version.
4 The name of the action. It is used both in the pom.xml and in the descriptor of the action (action.yml).
5 The description of the action. It is used both in the pom.xml and in the descriptor of the action (action.yml).
6 The full name of the GitHub repository hosting the action (in the form username/repository-name or org-name/repository-name).
7 The Quarkus GitHub Action extension. Add it right away so that the tooling can generate a full Quarkus GitHub Action application using Codestarts.

On Windows and macOS, it is recommended to concatenate all the options on one line (without \), as the \ might not be correctly interpreted.

This command creates a regular Quarkus Maven project. You can add additional Quarkus extensions or Java dependencies.

Once the project is created, go to the my-github-action directory:

cd my-github-action

Push to GitHub

If you have carefully followed the instructions above, you should be in your newly created project directory.

The next step is to push your GitHub Action to its GitHub repository (GitHub describes the instructions in the repository page):

git init
git add .
git commit -m "Init the project"
git branch -M main
git remote add origin git@github.com:my/action-github-repository.git (1)
git push -u origin main
1 Replace my/action-github-repository with the full name of the repository you created to host the GitHub Action.

Be careful to strictly follow the organization of the created project: the action.yml file must be at the root of your repository.

Once you pushed the repository to GitHub, the Publish action artifact to GitHub project’s Maven repository workflow will automatically publish your action to the Maven repository of the action’s repository.

Wait for it to complete before using your action. Go to the Actions tab of your action’s repository to check the workflow status.

When pushing new code to your action, the action will be updated only after the Publish action artifact to GitHub project’s Maven repository was completed successfully.

Let’s take a step back

Now is a good time to take a step back and have a closer look at what we pushed to the repository:

.
├── README.md (1)
├── mvnw (2)
├── mvnw.cmd (2)
├── pom.xml (3)
├── action.yml (4)
├── action.docker.yml (5)
└── src
    └── main
        ├── docker (6)
        │   ├── Dockerfile.jvm
        │   ├── Dockerfile.legacy-jar
        │   ├── Dockerfile.native
        │   └── Dockerfile.native-micro
        ├── java
        │   └── org
        │       └── acme
        │           └── MyAction.java (7)
        └── resources
            └── application.properties (8)
1 The root README.md. Add some content here so that users can understand what your GitHub Action does.
2 The Maven wrapper.
3 The pom.xml descriptor as we created a Maven project. Nothing specific here except a <distributionManagement> deploying the artifact to the repository’s Maven repository.
4 The action.yml descriptor, more on that later.
5 An alternative action.yml if you want to use a Docker-packaged native executable, more on that later.
6 Some default Dockerfiles provided for Quarkus. Only useful if using action.docker.yml.
7 A simple GitHub Action example.
8 An application.properties with some default configuration properties to silence Quarkus at startup (no banner, only log errors).

action.yml

action.yml is the GitHub Action descriptor and it is important to understand what it is doing.

The default one you obtain when creating a GitHub Action as described above is the following:

name: 'My Action' (1)
description: 'Description of my action' (2)
inputs:
  github-token: (3)
    description: 'GitHub token'
    required: true
  action: (4)
    description: 'Name of the action (if named)'
    required: false
runs:
  using: "composite" (5)
  steps:
    - name: Inject quarkus-github-action repository credentials (6)
      shell: bash
      run: |
        if [ -f ~/.m2/settings.xml ]; then
          if ! grep -q '<id>quarkus-github-action</id>' ~/.m2/settings.xml; then
            sed -i.bak 's@</servers>@<server><id>quarkus-github-action</id><username>${env.GITHUB_ACTOR}</username><password>${env.GITHUB_TOKEN}</password></server></servers>@' ~/.m2/settings.xml
          fi
        else
          mkdir -p ~/.m2/
          cat <<\EOF > ~/.m2/settings.xml
        <?xml version="1.0"?>
        <settings>
          <servers>
            <server>
              <id>quarkus-github-action</id>
              <username>${env.GITHUB_ACTOR}</username>
              <password>${env.GITHUB_TOKEN}</password>
            </server>
          </servers>
        </settings>
        EOF
        fi
    - name: Set up JBang
      uses: jbangdev/setup-jbang@main (7)
    - name: Run the action
      id: action
      run: jbang --java 21 --fresh --repos 'quarkus-github-action=https://maven.pkg.github.com/gsmet/my-github-action/' --repos 'mavencentral' org.acme:my-github-action:999-SNAPSHOT (8)
      shell: bash
      env:
        JSON_INPUTS: ${{ toJSON(inputs) }} (9)
        GITHUB_TOKEN: ${{ inputs.github-token }} (10)
1 The name of the action passed at creation.
2 The description of the action passed at creation.
3 The GitHub token is mandatory if you stick to publishing the action Maven artifact to the GitHub hosted Maven repository.
4 The optional action name, used for routing named actions to action methods.
5 The action is a composite action which has a few specificities. You can add additional steps if required.
6 Inject the credentials for the quarkus-github-action repository in the ~/.m2/settings.xml, allowing authenticated access to GitHub-hosted Maven repositories.
7 Install JBang, which is used to run the jar file.
8 Execute the jar file. It is downloaded from the Maven repository of the action GitHub repository. JBang will download a JDK if necessary.
9 Inputs are not transmitted to composite actions so we need to push them manually. The action will deserialize the JSON input automatically and make the inputs available.
10 The token is required to download the artifact from the GitHub hosted repository and will be used to authenticate the GitHub clients you can inject in your action code.

A composite action can be executed on all sorts of hosts, Linux, macOS or Windows.

Given it is a composite action, you can add additional steps to the action.

You can also tweak the existing steps of the action. For instance, if you want to use a Java version different from the one used by default for executing your code, you can adjust the action step as follows:

    - name: Run the action
      id: action
      run: jbang --java 17 --fresh --repos 'quarkus-github-action=https://maven.pkg.github.com/gsmet/my-github-action/' --repos 'mavencentral' org.acme:my-github-action:999-SNAPSHOT (1)
      shell: bash
      env:
        JSON_INPUTS: ${{ toJSON(inputs) }}
        GITHUB_TOKEN: ${{ inputs.github-token }}
1 Use --java 17 instead of --java 21.

Docker container action alternative

Another alternative is to build a Docker image with your application and use it as a Docker container action.

In the generated application, we provide both an alternative action.docker.yml (that you need to rename to action.yml) and a workflow file to publish the Docker image to the Docker repository of the action repository.

Using Docker container actions comes with some constraints as you can only run them on Linux hosts.

It is a limitation of GitHub Actions.

Except if you have specific requirements, it is recommended to use the default composite action approach.

application.properties

The default application.properties contains some configuration properties to make Quarkus startup silent:

quarkus.log.category."io.quarkus".level=SEVERE
quarkus.banner.enabled=false

MyAction.java

This file is just an example of a very simple action:

package org.acme;

import io.quarkiverse.githubaction.Action;
import io.quarkiverse.githubaction.Commands;

public class MyAction {

    @Action
    void action(Commands commands) {
        commands.notice("Hello from Quarkus GitHub Action");

        commands.appendJobSummary(":wave: Hello from Quarkus GitHub Action");
    }
}

The action() method will be called when the action is run on GitHub Actions and will:

  • Log a Hello from Quarkus GitHub Action notice

  • Append Hello from Quarkus GitHub Action to the job summary

Run your action

From there, everything is ready to run your simple GitHub Action, provided you waited for the Publish action artifact to GitHub project’s Maven repository initial workflow run of your action’s repository to finish.

To check if the Publish action artifact to GitHub project’s Maven repository workflow has run successfully, go to the Actions tab of the action’s repository.

Create a workflow in a separate repository with the following step:

      - name: Run my action
        uses: my/action-github-repository@main
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }} (1)
1 ${{ secrets.GITHUB_TOKEN }} is a temporary secret created by GitHub when initializing the workflow, you don’t need to define it yourself. The token is required when consuming the GitHub REST or GraphQL APIs so, in most cases, you need to pass it to the action.

You may call a Quarkus GitHub Action defined in a public repository from a public or private GitHub repository.

However, the workflow above will malfunction when the Quarkus GitHub Action is hosted in a private repository as the GitHub hosted Maven repository might not be accessible. The automatically generated GITHUB_TOKEN only grants access to private packages that are part of the same repository the workflow is defined in.

To use a Quarkus GitHub Action hosted in a separate private repository, please follow these steps:

  • Create or use a Personal Access Token with the read:packages scope. Depending on the GitHub API calls to be performed, additional permissions can be necessary.

  • In the repository, that is using the action, create a secret using the token.

  • The name you give to the secret (e.g. MY_ACTION_TOKEN) must in turn be referenced in the workflow configuration above: Replace ➀ with github-token: ${{ secrets.MY_ACTION_TOKEN }}.

After applying these steps, the workflow should be executed flawlessly.

It is important to mention though that secrets are not made available in workflows triggered by the pull_request event.

Next steps

Obviously, you can do a lot more with Quarkus GitHub Action and we describe all its features in the Developer reference.