How do I authenticating to remote repo inside Github Action using GH CLI? - github

I am having an issue with the following segment of a Github Action/Workflow which is meant to pull the PR list (with some filtering) of a remote, private repo (e.g. not the repo that contains the Action itself).
- run: echo "PR2=$( gh pr list --head "${{ env.BRANCH_NAME }}" --repo github.com/[OWNER]/[REMOTE_REPO] | tr -s [:space:] ' ' | cut -d' ' -f1 )" >> $GITHUB_ENV
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
However, I am getting the following error: GraphQL: Could not resolve to a Repository with the name '[OWNER]/[REMOTE_REPO]'. (repository)
I gather there is some issue with authentication somewhere, since the commands runs perfectly in a terminal after authenticating with gh auth. I'm new to Github as a whole, Actions, and CLI, so any advice as to how to properly authenticate inside an action would be amazing.
Edit: Found a solution/workaround.
Use git ls-remote to get a list of PRs and branches, then link the two using the ID. For future reference:
id=$(git ls-remote git#github.com:[OWNER]/[REMOTE_REPO] | grep "${{ env.BRANCH_NAME }}" | head -c 40)
PR=$(git ls-remote git#github.com:[OWNER]/[REMOTE_REPO] | grep "${id}.*refs/pull" | cut -b 52- | rev | cut -b 6- | rev)

There is an open feature request for authenticating non-interactively: Add flags to gh auth login to replace the interactive prompts
You can use github-script though:
steps:
- name: Find Pull Request
uses: actions/github-script#v5
with:
github-token: ${{ secrets.TOKEN_FOR_PRIVATE_REPO }}
script: |
const pulls = github.rest.pulls.list({
owner: '[OWNER]',
head: '${{ env.BRANCH_NAME }}',
repo: '[REMOTE_REPO]',
});
Note how it passes a separate github-token. The default token (secrets.GITHUB_TOKEN) cannot access your other private repository, so you'll have to issue another token and set that up as a secret.
If you don't want to use github script, you could also use plain curl with the newly issued token. Here's the doc on the REST API: https://docs.github.com/en/rest/reference/pulls#list-pull-requests and how to use the token: https://docs.github.com/en/rest/overview/other-authentication-methods#via-oauth-and-personal-access-tokens

You don't need to specifically authenticate using gh auth, but you should be using a generated PAT which has access to the private repo in this case.
For example, generate a PAT which can access your private repo, steps: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token
Add the PAT as a secret to the repo where you have your workflow, say PRIVATE_REPO_PAT , steps: https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository
Then, you can use that in your workflow like:
- run: echo "PR2=$( gh pr list --head "${{ env.BRANCH_NAME }}" --repo github.com/[OWNER]/[REMOTE_REPO] | tr -s [:space:] ' ' | cut -d' ' -f1 )" >> $GITHUB_ENV
env:
GITHUB_TOKEN: ${{ secrets.PRIVATE_REPO_PAT }}
Note that, if you do want to use gh auth 'non-interactively', say in a shell script, you could always do it using :
echo "$GH_CONFIG_TOKEN" | gh auth login --with-token
where GH_CONFIG_TOKEN is either the default GITHUB_TOKEN or a generated PAT.
For use in Github Actions, this auth is implicit when you pass in the correct GITHUB_TOKEN in the env variables.

Related

Using external action output in outer git action step

I have this git action for my build
...
- name: Building S3 Instance
uses: charlie87041/s3-actions#main
id: s3
env:
AWS_S3_BUCKET: 'xxx'
AWS_ACCESS_KEY_ID: 'xxx'
AWS_SECRET_ACCESS_KEY: 'xxxxx'
AWS_REGION: 'xxx'
- name: Updating EC2 [Develop] instance
uses: appleboy/ssh-action#master
with:
host: ${{secrets.EC2HOST}}
key: ${{secrets.EC2KEY}}
username: xxx
envs: TESTING
script: |
cd ~/devdir
export BUCKET_USER=${{steps.s3.outputs.user_id}}
export BUCKET_USER_KEY=${{steps.s3.outputs.user_key}}
docker login
docker-compose down --remove-orphans
docker system prune -a -f
docker pull yyyy
docker-compose up -d
And this is the important function in charlie87041/s3-actions#main
generate_keys () {
RSP=$(aws iam create-access-key --user-name $USER);
BUCKET_ACCESS_ID=$(echo $RSP | jq -r '.AccessKey.AccessKeyId');
BUCKET_ACCESS_KEY=$(echo $RSP | jq -r '.AccessKey.SecretAccessKey');
echo "user_id=$BUCKET_ACCESS_ID" >> $GITHUB_OUTPUT
echo "user_key=$BUCKET_ACCESS_KEY" >> $GITHUB_OUTPUT
echo "::set-output name=BUCKET_ACCESS_KEY::$BUCKET_ACCESS_KEY"
echo "::set-output name=BUCKET_ACCESS_ID::$BUCKET_ACCESS_ID"
}
I need to update env variables in container with BUCKET_USER and BUCKET_USER_KEY, but these always return null when echo the container. How do I do this?
Not that set-output was deprecated recently (oct. 2022)
If you are using self-hosted runners make sure they are updated to version 2.297.0 or greater.
If you are using runner on github.com directly, you would need to change
echo "::set-output name=BUCKET_ACCESS_KEY::$BUCKET_ACCESS_KEY"
with
echo "BUCKET_ACCESS_KEY=$BUCKET_ACCESS_KEY" >> $GITHUB_OUTPUT
I am not sure an export within the script would work.
Using with directives, as in issue 154 might be more effective
with:
BUCKET_USER: ${{steps.s3.outputs.user_id}}
...
script: |
...

Update dependabots pull request with version increment for other files for an Eclipse plug-in project

I use dependabots with Maven environment to receive pull requests on pom.xml files for version upgrades on all dependencies.
However, for an Eclipse plug-in project, more files need update:
MANIFEST.MF
build.properties
How do I configure dependabots in an Eclipse plugin project so that not only the pom.xml is updated but also MANIFEST.MF and build.properties?
An open feature request exists on dependabots
https://github.com/dependabot/dependabot-core/issues/5676
Meanwhile, I'm trying to tweak this with a Github Action that will checkout the branch from dependabots pull request and replace the version number in the files.
I've built this workflow file:
name: "Update dependabots"
on:
push:
branches: [ 'dependabot/**' ]
# Set the access for individual scopes, or use permissions: write-all
permissions:
pull-requests: write
issues: write
repository-projects: write
jobs:
build:
runs-on: ubuntu-latest
if: "contains(github.event.head_commit.message, 'Bump')"
steps:
- name: Checkout repository
uses: actions/checkout#v3
with:
ref: ${{ github.ref }}
- name: Setup git user
run: |
git config --global user.email "action#github.com"
git config --global user.name "GitHub Action"
- name: Update Version
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git log | grep -w Bump | cut -d' ' -f6,8,10 | xargs -n3 bash -c 'shopt -s globstar && sed -bi "s/$1-$2/$1-$3/g" **/MANIFEST.MF **/build.properties' sh-replace-in-files
git commit -a -m "Updated versions in **/MANIFEST.MF **/build.properties"
git push
But when the workflow runs, it complains that user github-actions[bot] is not allowed for my repository :
remote: Permission to myusername/myrepo.git denied to github-actions[bot].
fatal: unable to access 'https://github.com/myusername/myrepo/': The requested URL returned error: 403
Error: Process completed with exit code 128.
I tried to replace GITHUB_TOKEN with a PAT_TOKEN but no luck with that.
What should I do ?

How to view inputs for an action using github-cli while the action is running?

Is there a way to use the github-cli or api to view the inputs of an action while it is running?
I want to allow Github actions to run concurrently. The resources they will manage are determined by the input stack_name. I want to make sure two pipelines cannot run at the same time with the same stack_name input. If this happens, then I want one of the pipeline actions to fail and stop immediately.
I am also taking the input and turning it into an environmental variable for one of my jobs. After the job finishes, the values are available in the logs and I can grep through the following output to get a pipelines stack_name:
$ gh run view $running_pipeline_id --repo=$GITHUB_SERVER_URL/$GITHUB_REPOSITORY --log
....
env-check env-check 2022-03-22T17:06:30.2615395Z STACK_NAME: foo
However, this is not available while a job is running and I instead get this error:
run 1234567890 is still in progress; logs will be available when it is complete
Here is my current attempt at a code block that can achieve this. I could also use suggestions on how to make better gh run list and/or gh run view calls that can avoid using grep and awk. Clean json output I can parse with jq is preferable.
set +e
running_pipeline_ids=$(gh run list --workflow=$SLEEVE --repo=$GITHUB_SERVER_URL/$GITHUB_REPOSITORY \
| grep 'in_progress' \
| awk '{print $((NF-2))}' \
| grep -v $GITHUB_RUN_ID)
set -e
for running_pipeline_id in $running_pipeline_ids; do
# get the stack name for all other running pipelines
running_pipeline_stack_name=$(gh run view $running_pipeline_id --repo=$GITHUB_SERVER_URL/$GITHUB_REPOSITORY --log \
| grep 'STACK_NAME:' | head -n 1 \
| awk -F "STACK_NAME:" '{print $2}' | awk '{print $1}')
# fail if we detect another pipeline running against the same stack
if [ "$running_pipeline_stack_name" == "$STACK_NAME" ]; then
echo "ERROR: concurrent pipeline detected. $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$running_pipeline_id"
echo "Please try again after the running pipeline has completed."
exit 1
fi
done
Perhaps you could use the concurrency feature of GitHub Actions?
Now you cannot directly bake this into an action, but if it's possible for you to extract your action into a reusable workflow then you could make use of the concurrency feature.
It would look something like this:
# ./github/workflows/partial.yaml
on:
workflow_call:
inputs:
stack-name:
description: "name of the stack"
required: true
type: string
jobs:
greet:
runs-on: ubuntu-latest
concurrency:
group: ${{ inputs.stack-name }}
cancel-in-progress: true
steps:
- uses: my/other-action
with:
stack_name: ${{ inputs.stack-name }}
And then where you're using it:
jobs:
test:
uses: my/app-repo/.github/workflows/partial.yml#main
with:
stack-name: 'my-stack'

How to get branch name for tagged build on GitHub actions

I want to push docker images to Docker Hub on tagged commits on the master branch.
Everything I've tried (How to get branch name on GitHub action?, lots of action plugins, like https://github.com/tj-actions/branch-names) only give me the tag name, but I need to know the branch name.
Specifically what I want to do is push a docker image to docker hub on tagged commits on master branch.
After a while I understood why this was not possible: When running a build based on the tagging event, the git checkout is not on a branch at all (it is a detached head).
It is possible to find the branch though, using git branch -a --contains <tag name> and a full checkout (fetch-depth: 0).
docker_tagged:
name: Tagged - Docker push to tag based on git tag. Also push 'latest' if on master
needs: tests
runs-on: ubuntu-latest
if: startsWith(github.event.ref, 'refs/tags')
steps:
- uses: actions/checkout#v2
with:
fetch-depth: 0
- run: echo "TAG=${GITHUB_REF#refs/*/}" | tee -a $GITHUB_ENV
- run: echo "BRANCH=$(git branch -a --contains ${{ env.TAG }} | grep -v HEAD | cut -d '/' -f3)" | tee -a $GITHUB_ENV
- uses: docker/login-action#v1
with:
username: locustbuild
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- uses: docker/build-push-action#v2
with:
push: true
tags: locustio/locust:${{ env.TAG }}${{ ( env.BRANCH == 'master' && ',locustio/locust:latest') || '' }}
(note that this will probably break if a tag is on master and another branch too)

Get PR Number OR Branch Name in GitHub Actions

I'm trying to deploy a serverless application on merge into develop & master AND on PR request. I want the stage name to correspond to the branch name OR pull request number.
This is the step in question, but github.event.push.ref is the entire branch ref (i.e. ref/head/master) etc. And I just want "master" or "develop". Is there anyway to use this same syntax as below to get pull_request number OR branch name?
# Deploy API Tests
- name: Deploy API
run: yarn deploy --stage ${{ github.event.pull_request.number || github.event.push.ref }}
working-directory: api
If the shell you're using is bash or another POSIX shell, it's easy enough to do this:
run: 'yarn deploy --stage $(echo "${{ github.event.pull_request.number || github.event.push.ref }}" | sed -e 's!^refs/heads/!!')'
That will strip off the refs/heads/ prefix and leave you with just the branch name. If you were not using a PR, then you could also use this, which would have Git abbreviate the name to just the branch or tag name:
run: 'yarn deploy --stage $(git rev-parse --abbrev-ref "${{ github.event.push.ref }}")'