How to get a git ref from within GitHub Actions? - github-actions

This is what I am trying:
- name: Create tag
uses: actions/github-script#v3
with:
script: |
console.log(await github.git.getRef({
owner: context.repo.owner,
ref: "refs/tags/v0.0.1",
repo: context.repo.repo,
}));
However, it is producing "Not Found" error.
If I check using git, I can see that tag exists:
$ git ls-remote
From git#github.com:contra/contra-deploy-tools.git
fc857fff2008eca7c4a547ad4bb35cd7ef5f3891 HEAD
fc857fff2008eca7c4a547ad4bb35cd7ef5f3891 refs/heads/main
b4e20f75a51aac030e3d8ca1360ee1ff84f10c18 refs/tags/v0.0.1
It appears like this is a permission issue. However, I am able to create a tag, and workflow permissions are configured to "Read and write permissions".
What's more surprising is that I am able to list references within the workflow:
Run git ls-remote
From https://github.com/contra/contra-deploy-tools
f0191b469168aa48ee177d270fa2af507d3f7710 HEAD
f0191b469168aa48ee177d270fa2af507d3f7710 refs/heads/main
b4e20f75a51aac030e3d8ca1360ee1ff84f10c18 refs/tags/v0.0.1
This seems to be API specific issue.
What am I missing?

You don't need the refs/ prefix in that API. Looking at the docs, it says that:
Returns a single reference from your Git database. The :ref in the URL must be formatted as heads/ for branches and tags/ for tags.
So if you change your step to the below, it should work.
- name: Create tag
uses: actions/github-script#v3
with:
script: |
console.log(await github.git.getRef({
owner: context.repo.owner,
ref: "tags/v0.0.1",
repo: context.repo.repo,
}));
NB: You're using github-script version 3, but there's already v5. If you want to keep your actions up to date, I previously described how that can be done using dependabot: https://stackoverflow.com/a/70196496/1080523

Related

How to make a Github Actions workflow update a Check on a Pull Request comment?

I am trying to use GitHub Actions to validate the book-keeping side of pull requests. Basically, the idea is that merging should be blocked unless certain tags, milestones, and other information is present in the PR. The logic I am currently struggling with is this: The PR needs to have one of two labels, "no release notes" or "public release notes" and if the "public release notes" label is present, then a specially formatted comment should be present with the release notes in question.
I have succeeded in getting the action to fire and update the check when the PR is created, or a label is added or removed. These paths modify the check status on the PR itself.
However, while I can get the Action to run when I add a PR comment (issue comment) this does not seem to update the check status. Is it possible to use an issue comment event to modify the check status of the PR directly?
The YML for the action is:
name: Github PR Audit
on:
pull_request:
types:
- opened
- edited
- labeled
- unlabeled
issue_comment:
types:
- created
- edited
- deleted
jobs:
Audit-Pull-Request:
runs-on: ubuntu-latest
steps:
You can use the GitHub Script GH Action + Branch protection rules configuration.
GitHub Script Action provides an easy and elegant way to run scripts in your workflow and Branch protection rules allow configuring which status checks must pass before branches can be merged.
Example workflow:
name: Github PR Audit
on:
pull_request:
types:
- opened
- edited
- labeled
- unlabeled
issue_comment:
types:
- created
- edited
- deleted
jobs:
Audit-Pull-Request:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script#v6
with:
script: |
const requiredLabels = ['no release notes', 'public release notes'];
let labels = [];
if (context.payload.pull_request) {
labels = context.payload.pull_request.labels;
} else if (context.payload.issue) {
labels = context.payload.issue.labels;
}
if (labels.filter(l => requiredLabels.includes(l.name)).length === 0) {
throw new Error(`Required labels: ${requiredLabels.join(', ')}`);
}
This script will check if its context has the corresponding labels and will fail if not.
Example failing run:
Branch protection rule configuration:
Creating a branch protection rule

Convert a string or json value to YAML array for GitHub Actions

I am trying to dynamically build secrets into this GitHub action library for my pipeline.
I need to preprocess and generate all the secrets (pulled from AWS). After, I want to dynamically inject those secrets into this GitHub action.
Node.js script
let secrets = generateArrayOfSecrets() //[AWS_KEY=123, API_TOKEN=345]
let envFile = convertToEnvFile(secrets)
fs.writeFileSync(process.env.PUT_FILE || '.env.read', envFile)
Echo output form node.js file
echo "::set-output name=SECRETS::$(cat .env.read)"
Dynamically build secrets
- name: Build, Tag, and Push Image to Amazon ECR
uses: docker/build-push-action#v3
with:
push: true
secrets: ${{ steps.secret.outputs.SECRETS }}
This isn't working, and it is treating it as a single value. My question is, how can I convert a string to a real YAML array? Any help would be greatly appreciated here.
According to the secrets section on the docker.build-push-action action repository, you can expose a secret file to the build with the secret-files input.
Something like this:
name: Build
uses: docker/build-push-action#v3
with:
push: true
secret-files: |
"MY_SECRET=./secret.txt"
As you are already creating an envFile with the secrets in your Node script, this solution seems more adapted, as you won't need to parse it to get each secret key/value.
PS: This secret files needs to follow the Docker docs build pattern

How to get a GitHub Action step to run only on branches with a particular name prefix?

I am writing a GitHub Action. I want some of my steps to run only on certain branches.
The whole action is set to run only on master and on branches beginning with features/lr.
on:
push:
branches:
- master
- features/lr*
I have a "deploy" step that I want to run on master and on branches beginning with features/lrd. (So for example if my branch is named features/lr-foo, then the deployment step should be skipped.)
I know I can do if conditionals like this:
- name: Deploy application
if: github.ref == 'refs/heads/master'
Can I also check whether github.ref matches a certain prefix or pattern? What is the syntax for that?
Something like this pseudocode:
- name: Deploy application
if: github.ref == 'refs/heads/master' || github.ref.matches('refs/heads/lrd*')
Thanks in advance!
The branches, branches-ignore, tags, and tags-ignore keywords accept glob patterns. You can check details in docs - filter pattern.
As for using expressions, docs don't mention matches function, but maybe you could use something like contains, startsWith or endsWith. See here for details.
Inspired by the answer from frennky, I ended up doing the following in my step, which is ugly but works:
- name: Deploy application
if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/features/lrd')

Is pull_request.label available to a Github Action?

I am trying to start a workflow only if the merged pull_request has a specific label.
The merged key is referenced here within an action. The Pull object itself is documented here. But I don't see merged documented by itself or with other keys.
Is pull_request.label available to a Github Action? Is there a comprehensive doc that shows all the keys available to a pull_request?
To list all labels you can use something like this
x=${{ toJson(github.event.pull_request.labels.*.name) }}
echo $x
Also to use a single label you can try
steps:
- name: deploy
if: contains(github.event.pull_request.labels.*.name, 'deploy')
run: |
echo "deploy"

Add check to a specific workflow-run/check-suite using octokit

I have a project with Github Actions that implements multiple workflows that can be triggered by a single push event (depending on path filter).
So a push with a single commit can trigger multiple workflows, so far so good.
In each workflow I am running actions/github-script to create dynamic run-checks with the following step:
- uses: actions/github-script#v4
with:
github-token: ${{ inputs.github-token }}
script: |
const date = new Date();
const check = await github.checks.create({
owner: "${{ steps.vars.outputs.owner }}",
repo: "${{ steps.vars.outputs.repo }}",
name: "Custom Script",
started_at: date.toISOString(),
completed_at: date.toISOString(),
head_sha: "${{ inputs.sha }}",
external_id: "${{ github.run_id }}",
status: "completed",
conclusion: "success",
output: {
title: "Some funny title",
summary: "Build successful",
text: "Image pushed to https://${{ inputs.region }}.console.aws.amazon.com/ecr/repositories/private/${{ inputs.customer-id }}/modix/base/${{ inputs.image }}"
}
});
It is working like a charm, when a single workflow is triggered, but as soon as a push triggers multiple workflows, then only the first one that runs is showing the added check. all others but the first don't show the check but also no error?
Before I have tried the LouisBrunner/checks-action and it had the same problem so I created an issue: https://github.com/LouisBrunner/checks-action/issues/26. But now that it also fails by directly using octokit with github-script action, it feels like the problem is somewhere else...
UPDATE:
According to Gregors answer, I have tried giving the check a different name in each workflow by appending the run-id, I found that each parallel workflow is adding the check to the workflow that runs first... so the question now is, how to send it to a specific workflow run?
according to these docs, there is no dedicated parameter for that, it seems that it automatically detects the workflow using the head_sha?
name: "Custom Script ${{ github.run_id }}",
Try setting Custom Script to something different for each check run you create. I think multiple check runs with the same names are collapsed into only showing the last one. The reason is that that way you can override an status on a commit, by using the same name.
Sadly I found that it is simply impossible to attach a check to a specific workflow-run or check-suite. The problem is known for over a year now, but they didn't provide any solution yet. See in this thread.
In the name of a big automotive company, I have now submitted a feature request in the official feedback form of github.
PS: If the feature will be implemented in the future, I am going to create and accept another answer here.