从GitHub操作中推送到远程仓库的方法

90

我正在尝试从GitHub操作推送到origin远程。我的操作逻辑如下:

  • 处理pull_request_review事件并按评论消息进行过滤
  • 检出到主分支,合并PR分支,运行一些检查,并将其推送到origin

脚本如下:

if [[ "${GITHUB_EVENT_NAME}" != "pull_request_review" ]]; then
  echo "unsupported event: ${GITHUB_EVENT_NAME}"
  exit 1
fi

user=$(jq -r .review.user.login ${GITHUB_EVENT_PATH})
cmd=$(jq -r .review.body ${GITHUB_EVENT_PATH})
echo "reviewer is ${user}, command is ${cmd}"

if [[ "${cmd}" == "merge" ]]; then
  head=$(jq -r .pull_request.head.ref ${GITHUB_EVENT_PATH})
  git config user.email test@test.com
  git config user.name test
  git checkout -B _tmp origin/${head}
  git checkout -B master origin/master
  git merge --no-ff _tmp
  git push origin master
fi

我在 alpine:3.10 Docker 容器中运行这个脚本:

FROM alpine:3.10

LABEL "com.github.actions.name"="Hello world action"
LABEL "com.github.actions.icon"="shield"
LABEL "com.github.actions.color"="green"

WORKDIR /app
COPY action.sh action.sh
RUN apk --update add bash git jq
CMD ["bash", "/app/action.sh"]

首次操作(检出和合并)是正常的,但由于错误,操作未能将合并推送到origin

+ git push origin master
fatal: could not read Username for 'https://github.com': No such device or address

看起来GitHub-action Docker容器未配置用于向GitHub推送。如何进行配置?是否可以使用GitHub提供的一些环境变量或者一些挂载文件(例如/github/*路径)?

6个回答

231
从版本2开始的checkout操作,已经解决了分离HEAD状态的问题,并简化了推送到远程仓库的过程。
name: Push commit
on: push
permissions:
  contents: write
jobs:
  report:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Create report file
        run: date +%s > report.txt
      - name: Commit report
        run: |
          git config --global user.name 'Your Name'
          git config --global user.email 'your-username@users.noreply.github.com'
          git commit -am "Automated report"
          git push

如果您需要推送事件来触发其他工作流程,请使用一个作用域为repo个人访问令牌
      - uses: actions/checkout@v3
        with:
          token: ${{ secrets.PAT }}

actions/checkout@v1(原始答案)

为了对@rmunn的出色回答进行进一步说明,问题在于actions/checkout@v1操作会使git仓库处于分离HEAD状态。有关此问题的更详细信息,请参阅此问题:https://github.com/actions/checkout/issues/6

下面是一个完整的示例,演示如何将检出的仓库转换为可用状态并推送到远程仓库。

name: Push commit
on: push
jobs:
  report:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: Create report file
        run: date +%s > report.txt
      - name: Commit report
        run: |
          git config --global user.name 'Your Name'
          git config --global user.email 'your-username@users.noreply.github.com'
          git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY
          git checkout "${GITHUB_REF:11}"
          git commit -am "Automated report"
          git push

要包含未跟踪的(新的)文件,请将工作流更改为使用以下内容。
          git add -A
          git commit -m "Automated report"

上述工作流程适用于大多数事件。对于“on: pull_request”工作流程,合并分支(GITHUB_HEAD_REF)应被检出以替换默认的合并提交。
重要提示:如果您除了以下工作流程之外还有其他拉取请求检查,则必须使用个人访问令牌而不是默认的GITHUB_TOKEN。 这是由GitHub Actions强制实施的一项有意限制,即工作流程引发的事件(如push)不能触发进一步的工作流程运行。 这是为了防止意外的“无限循环”情况,并作为一种反滥用措施。 使用一个具有“repo”范围的个人访问令牌是一种已批准的解决方法。有关解决方法的详细信息,请参阅此GitHub问题
name: Push commit on pull request
on: pull_request
jobs:
  report:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
        with:
          ref: ${{ github.head_ref }}
      - name: Create report file
        run: date +%s > report.txt
      - name: Commit report
        run: |
          git config --global user.name 'Your Name'
          git config --global user.email 'your-username@users.noreply.github.com'
          git remote set-url origin https://x-access-token:${{ secrets.PAT }}@github.com/${{ github.repository }}
          git commit -am "Automated report"
          git push

进一步了解在“on: pull_request”工作流期间将推送到源代码的示例,请参阅此博文:GitHub Actions: 如何自动化代码格式化以进行拉取请求

3
提交前,有没有一种方法可以检查是否有文件被更改?这样在测试或使用多个节点版本时就可以避免错误地出现问题,因为提交已经使用工作流的第一次运行推送了。 - limitlessloop
2
对于任何好奇的人,checkout@v2凭据存储在git config http.https://github.com/.extraheader中。 - Mingwei Samuel
@limitlessloop 使用 git status - Andres Mitre
1
@commonpike 对于分支上的“push”事件,这并不是必需的。也许您混淆了“push”和“pull_request”事件? - peterevans
如果没有需要提交的内容,则提交将失败。如何确切地防止这种情况发生? - Nico Schlömer
显示剩余3条评论

21
你可以使用secrets.GITHUB_TOKEN作为您的存储库URL上的密码。因此,在您的git push行之前,您可以添加此内容:
git remote set-url --push origin https://your_username:$GITHUB_TOKEN@github.com/your/repo

这假设你已经将GITHUB_TOKEN密钥作为环境变量传递给脚本。如果你还没有这样做,那么添加:


GITHUB_TOKEN=your_token_here

到你的脚本中。

env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

添加到您的工作流步骤中。


谢谢。但是当我使用https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git作为远程URL时,我遇到了另一个错误:remote: Invalid username or password.。这个GITHUB_TOKEN属于github-actions应用程序,所以我不能像普通用户一样使用它。你知道我应该使用什么用户名来使用这个令牌吗? - Kirill
你是否按照 https://help.github.com/en/articles/virtual-environments-for-github-actions#github_token-secret 中的说明,将token作为环境变量传递给脚本?我不知道你所说的“我不能用它作为普通用户”,只要你按照那些说明将它作为环境变量传递给脚本,它就可以在你的脚本中使用。至于用户名,它是你仓库的用户名:例如,对于我的 https://github.com/rmunn/Testing 仓库,用户名将是 rmunn - rmunn
我找到了问题所在:我无法在Docker操作中使用env,需要编写带有token输入的action.yml配置,并在工作流程yml中使用with关键字将其作为输入传递。 - Kirill

11
以下是使用官方 Github Action actions/checkout@v3 的示例:
name: Example Push Action
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: |
          date > generated.txt
          git config user.name github-actions
          git config user.email github-actions@github.com
          git add .
          git commit -m "generated"
          git push

得到一个403。远程:github-actions[bot]被拒绝对<REPO>的权限。 - samlaf
@samlaf 或许 这个问题 可以帮助你。 - Vadik Sirekanyan
1
是的,缺少“contents: write”权限。谢谢! - samlaf

8
所有的回答都很好,不过我应该指出有一个 GitHub Action Add & Commit 可以大大简化这个过程。
name: Commit Date
on: push

jobs:
  run:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: Create report file
        run: date +%s > report.txt

      - name: Commit changes
        uses: EndBug/add-and-commit@v9
        with:
          author_name: Your Name
          author_email: mail@example.com
          message: 'Your commit message'
          add: 'report.txt'

5

所有提供的答案都是正确的。但我想多添加一点内容。有时候文件没有任何更改。在这种情况下,尝试执行git commit命令会返回一个错误,导致GitHub工作流程失败(失败的工作流程将阻止PR合并)。因此,在提交之前,我们必须检查文件是否有任何更改。

name: Config Generator
on:
  pull_request:
    branches: [ main ]

jobs:
  config-generator:
    runs-on: ubuntu-latest
    steps: 
      - uses: actions/checkout@v2
        with:
          ref: ${{ github.head_ref }}

      - name: Install jsonnet
        run: sudo apt install -y jsonnet

      - name: Generate probe configs
        run: python3 generate-configs.py

      - name: Check for modified files
        id: git-check
        run: echo ::set-output name=modified::$(if [ -n "$(git status --porcelain)" ]; then echo "true"; else echo "false"; fi)

      - name: Update changes in GitHub repository
        if: steps.git-check.outputs.modified == 'true'
        run:  |
          git config --global user.name 'Your Name' 
          git config --global user.email 'Your Email for GitHub'
          git add -A
          git commit -m '[automated commit] add configs generated using jsonnet & GitHub workflow'
          git push

上述工作流程是使用jsonnet和GitHub工作流程创建配置文件的示例。首先安装jsonnet,然后运行一个Python脚本,使用jsonnet模板创建配置文件。如上所述,可能存在没有文件更改的情况。因此,它使用git status命令检查是否有文件更改。 (可以使用git diff替代git status。但是它不会显示未跟踪的文件)。只有在存在文件更改时,其余的git命令才会运行。
另请注意,我必须使用ref: ${{ github.head_ref }}来检出源分支,尽管我使用了checkout@v2(在我的情况下仍然存在分离头问题)。

3

如果想要自动提交而不定义用户或其他任何内容,请使用EndBug/add-and-commit@v7。这是我的工作流文件,用于自动格式化和提交js和python代码。

name: auto-format
on: push
jobs:
  format-python:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: black
        uses: lgeiger/black-action@v1.0.1
        with:
          args: .

      - uses: EndBug/add-and-commit@v7
        with:
          default_author: github_actions

  format-js:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: prettier
        run: npx prettier --write "./**/*.{js,html}"

      - uses: EndBug/add-and-commit@v7
        with:
          default_author: github_actions



网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接