bashgithubyamlgithub-actionsbuilding-github-actions

How can I push changes to a private repository using github actions


The problem

I'm trying to push changes to my repository using Github Actions. The changes consists of appending the README.md file with a link each time a new markdown file is created within the projects/ directory inside my repo.

My repo is private and I want to keep it that way. But still want to be able to push some predefined changes it some specific files.

Everything works as intended except one thing. Here is the output log from Github Actions:

remote: Write access to repository not granted.
fatal: unable to access 'https://github.com/USERNAME/REPO_NAME.git/': The requested URL returned error: 403
Error: Process completed with exit code 128.

from the looks of this I'm not authorized to push my desired changes from within the Github Actions Container to my private repo.

NOTE: Im looking for a better way other than to clone my repo within the Actions container. If there is a better way to do this let me know. Thanks!

Here is what I'm trying to do:

My repository file structure is as follows:

 - README.md
   |- projects
      |- markdownfile_01.md
      |- markdownfile_02.md
      |- markdownfile_03.md 

so what i want is to append the README.md file with a link ... something like this:

- [filename](link_to_newly_created_file)

This link refers to .md file created in projects directory. It will be shown in the README.md file like an index page.

the YAML file I'm using for this workflow is:

name: Update README

on:
  push:
    paths:
      - 'projects/*.md'

jobs:
  update-readme:
    runs-on: ubuntu-latest
    steps:
      - name: Check out the repository
        uses: actions/checkout@v2
      
      - name: Get file name
        id: file-name
        run: |
          commit_message=$(git log --format=%B -n 1 ${{ github.sha }})
          echo "==> COMMIT MESSAGE: $commit_message"
          file_name=$(echo $commit_message | cut -d' ' -f2)
          echo "::set-output name=file_name::$file_name"
      
      - name: Update README
        env:
              # Use the secret that you stored earlier
              ACTIONS_GITHUB_TOKEN: github_pat_some_random_key
        run: |
          # cloning current repo where the YAML file is present
          git clone https://github_pat_some_random_key@github.com/${{ github.actor }}/projects-repo
          echo "==CLONED SUCCESSFULLY=="

          # fetching file data
          file_name=${{ steps.file-name.outputs.file_name }}
          echo "==> FILE NAME: $file_name"
          base_name=$(basename $file_name .md)
          echo "==> $base_name"

          # generating text to append to README.md
          link="- [$base_name]($file_name)"
          echo "==> LINK: $link"

          # checking if file was created in projects directory
          if [ -f "projects/$file_name" ]; then
            echo "$link" >> README.md
            echo "FILE EDITED"
          else
            sed -i "/$link/d" README.md
            echo "REMOVED LINE"
          fi     

          # check if it is written or not
          cat README.md

          # pushing back to repository          
          git config --global user.name '${{ github.actor }}'
          echo "==> ACTOR: ${{ github.actor }}"
          git config --global user.email '${{ github.actor }}@users.noreply.github.com'
          echo "==> URL: ${{ github.actor }}@users.noreply.github.com"
          # adding repository
          git remote add private-repo https://github.com/Blankscreen-exe/projects-repo.git
          
          git push -f private-repo ${{ github.ref }}:main
          git add README.md
          git commit -m "Update README with link to ${{ steps.file-name.outputs.file_name }}"
          git push origin ${{ github.ref }}

Solution

  • You have many options, but in this case a deploy key would probably be the easiest solution. Add the token to your Action's Secrets tab and use it to authenticate to the private repo.

    The full process is explained here, though instead of committing the key encrypted to git, I'd probably store it in a GitHub Secret instead.

    Create a ssh token and commit it to git:

    ssh-keygen -t rsa -b 4096 -f .github/workflows/secrets/id_rsa -C "ios-provisioning@eclipsesource.com" -N ""
    $ # generate encryption password we will use in OpenSSL
    $ export ENCRYPTION_KEY $(pwgen 32 1)
    $ openssl aes-256-cbc -in .github/workflows/secrets/id_rsa -out .github/workflows/secrets/id_rsa.enc -p
    

    Add the encrytion key as a secret in Actions.

    Then use the token in your workflow:

    name: Deploy Key test
     
    on:
      push:
      
    jobs:
      main:
        runs-on: ubuntu-latest
        name: Access private repo
        steps:
     
          - name: Checkout secrets
            uses: actions/checkout@v2
     
          - name: Decrypt secrets
            env:
              ENCRYPTION_KEY: ${{ secrets.ENCRYPTION_KEY }}
            run: |
              openssl aes-256-cbc -in .github/workflows/secrets/id_rsa.enc -out .github/workflows/secrets/id_rsa -pass pass:$ENCRYPTION_KEY -d -md sha1
     
          - name: Setup SSH agent
            env:
              SSH_AUTH_SOCK: /tmp/ssh_agent.sock
            run: |
              mkdir -p ~/.ssh
              ssh-keyscan github.com >> ~/.ssh/known_hosts
     
              ssh-agent -a $SSH_AUTH_SOCK > /dev/null
              chmod 0600 .github/workflows/secrets/id_rsa
              ssh-add .github/workflows/secrets/id_rsa
     
          - name: Checkout
            env:
              SSH_AUTH_SOCK: /tmp/ssh_agent.sock
            run: git clone git@github.com:eclipsesource/ios-provisioning.git
     
          - name: Cleanup
            if: always()
            env:
              SSH_AUTH_SOCK: /tmp/ssh_agent.sock
            run: |
              ssh-add -D
              rm -Rf *