Skip to main content

Command Palette

Search for a command to run...

Workflow dispatch - Github actions

Use case for workflow dispatch in real world

Published
3 min readView as Markdown
Workflow dispatch - Github actions
U

I am a Software Engineer 2 at a Fintech company and am motivated with devops procedures and interested in learning new cloud technologies.

To give a brief about this tool, we need to understand github workflow triggers. Usually in a workflow yaml we mention a event that triggers that particular workflow. For example, we use specific github activities like pushing to a branch. Another is scheduling jobs to trigger the flow say every 2 hours.

Similarly workflow_dispatch is another way to trigger workflow from an external application. I recently got a requirement to use this in my project.

Prerequisites are

  1. Write access to repo is required

    This can be achieved by creating a Github app access token / installation token or personal access token

In order to get write access to repo, I created a github app and gave access to my repo. The github app is a way to connect to github events from external code. So create a new github app and give permissions to your repository. Also in order to authenticate to app we need an private key (created through ssh while creation of app).

Through code we can create jwt token and also github access token.

Note: For each app will have certain permissions that can be assigned . In our case workflow permission must be set to ‘Read and write‘ for this app

private string GenerateJwt()
{
    var privateKey = File.ReadAllText(@"path to pem file");
    var rsa = RSA.Create();
    rsa.ImportFromPem(privateKey.ToCharArray());

    var securityKey = new RsaSecurityKey(rsa);
    var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.RsaSha256);

    var handler = new JwtSecurityTokenHandler();
    var token = handler.CreateJwtSecurityToken(
        issuer: "App_Id", // replace with app id
        signingCredentials: credentials,
        notBefore: DateTime.UtcNow.AddMinutes(-1),
        expires: DateTime.UtcNow.AddMinutes(10)
    );

    return handler.WriteToken(token);
}

private async Task<string> GetAccessToken()
{
    var jwt = GenerateJwt();
    var installId = "App_install_ID"; // replace with application's install id 

    using var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwt);
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.github.v3+json"));

    var payload = new { repositories = new[] { "Repo name" } }; // replace with repository name
    var content = new StringContent(JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json");

    var response = await client.PostAsync($"https://{githubHost}/api/v3/app/installations/{installId}/access_tokens", content);
    var json = await response.Content.ReadAsStringAsync();
    dynamic result = JsonConvert.DeserializeObject(json);
    Console.WriteLine(result.token);
    return result.token;
}
  1. Now, we can run the workflow either manually via Github actions or by using a REST API to trigger this workflow. Inputs can also be configured during this API call.

Now let’s see how I used REST API in my C# application. We can pass up to 10 inputs to the API like branch name, environment ..etc for more control

As next step we can use above token to trigger workflow from C# app


        var payload = new
        {
            @ref = "main",
            inputs = new { environment , branch }
        };

        var json = JsonConvert.SerializeObject(payload);
        var content = new StringContent(json, Encoding.UTF8, "application/json");

        var url = $"https://api.github.com/repos/{RepoOwner}/{RepoName}/actions/workflows/{WorkflowFileName}/dispatches";
        var response = await client.PostAsync(url, content);

        // check the status of workflow from response
  1. Final step is to mention the trigger in our workflow file -
# .github/workflows/manual-trigger.yml
name: Manual Trigger Workflow

on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Environment to deploy'
        required: true
        default: 'dev'
      branch:
        description: 'branch name on which we deploy'
        required: true
        default: 'main'

jobs:
  run-script:
    runs-on: ubuntu-latest
    steps:
      - name: Echo environment
        run: echo "Deploying to ${{ github.event.inputs.environment }}"

This is a practical use case for triggering the github workflow from external application.
Stay tuned for more!!