You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过GitHub Actions向私有仓库推送变更?权限问题求解

问题概述

我想用GitHub Actions实现:当私有仓库的projects目录新增Markdown文件时,自动在README.md里追加对应文件的链接(格式为- [文件名](文件路径)),把README做成索引页。但目前遇到两个问题:

  • 推送变更时触发403错误,提示无写入权限
  • 当前Workflow里重复克隆了仓库,想优化掉这个操作

仓库结构

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

期望追加的链接格式

- [filename](link_to_newly_created_file)

当前使用的Workflow配置

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 }}

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.

解决方案

1. 解决403权限错误

问题根源

  • 硬编码的PAT存在泄露风险,且默认ACTIONS_GITHUB_TOKEN仅拥有仓库读权限,无法写入私有仓库
  • 推送逻辑顺序错误:先执行了git push,但此时还未完成README的修改、提交操作

修复步骤

  1. 生成并存储PAT:
    • 在GitHub账号设置中生成带repo权限的Personal Access Token(确保拥有私有仓库读写权限)
    • 在目标仓库的Settings > Secrets and variables > Actions中添加名为REPO_PUSH_TOKEN的Secret,值为生成的PAT
  2. 修正权限与推送逻辑:使用存储的Secret令牌进行仓库拉取和推送,避免硬编码

2. 优化重复克隆问题

actions/checkout已经完成了仓库克隆,直接在当前工作目录操作文件即可,无需重复执行git clone


修正后的完整Workflow

name: Update README

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

jobs:
  update-readme:
    runs-on: ubuntu-latest
    steps:
      - name: Check out the repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          token: ${{ secrets.REPO_PUSH_TOKEN }}

      - name: Get changed Markdown files
        id: changed-files
        run: |
          changed_files=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }} | grep 'projects/.*\.md$')
          echo "changed_files<<EOF" >> $GITHUB_OUTPUT
          echo "$changed_files" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: Update README.md
        run: |
          git config --local user.name "${{ github.actor }}"
          git config --local user.email "${{ github.actor }}@users.noreply.github.com"

          while IFS= read -r file; do
            base_name=$(basename "$file" .md)
            link="- [$base_name]($file)"
            
            if [ -f "$file" ]; then
              if ! grep -qF "$link" README.md; then
                echo "$link" >> README.md
                echo "Added link: $link"
              fi
            else
              sed -i "/$link/d" README.md
              echo "Removed link: $link"
            fi
          done <<< "${{ steps.changed-files.outputs.changed_files }}"

          if git diff --quiet README.md; then
            echo "No changes to README.md"
            exit 0
          fi

          git add README.md
          git commit -m "Update README with links to changed project files"
          git push origin ${{ github.ref }}

关键优化点

  • 移除重复克隆操作,直接使用actions/checkout拉取的工作目录
  • 用Secrets存储PAT,确保权限安全且具备读写能力
  • 通过git diff检测变更文件,替代从commit message提取文件名的不可靠方式
  • 添加链接前先检查是否已存在,避免重复追加
  • 修正提交推送顺序,逻辑更合理

内容的提问来源于stack exchange,提问作者White_noise

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 10:01:10