从 GitHub 动作推到原点

我正试图从 GitHub 操作推到 origin远程。我的操作逻辑是:

  • 处理 pull_request_review事件并通过注释消息进行过滤
  • 检查到主,合并公关分支,运行一些检查,并推到 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 推动原点主机
不能读取“ https://github.com”的用户名: 没有这样的设备或地址

看起来 GitHub-action Docker 容器没有配置为推送到 GitHub。我如何配置它?是否可以使用 GitHub 提供的一些 Env 变量或者一些挂载的文件(比如在 /github/*路径中) ?

53601 次浏览

You can use secrets.GITHUB_TOKEN as a password on your repository URL. So you might add this before your git push line:

git remote set-url --push origin https://your_username:$GITHUB_TOKEN@github.com/your/repo

This assumes that you're already passing in the GITHUB_TOKEN secret as an environment variable to your script. If you aren't, then add:

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

to your workflow step.

actions/checkout@v2

Version 2 of checkout resolves the detached HEAD state issue and simplifies pushing to origin.

name: Push commit
on: push
jobs:
report:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- 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

If you need the push event to trigger other workflows, use a repo scoped Personal Access Token.

      - uses: actions/checkout@v2
with:
token: $\{\{ secrets.PAT }}

actions/checkout@v1 (original answer)

To add some further detail to the excellent answer by @rmunn. The problem is that the actions/checkout@v1 action leaves the git repository in a detached HEAD state. See this issue about it for more detailed information: https://github.com/actions/checkout/issues/6

Here is a complete example to demonstrate how to get the checked out repository to a usable state and push to the remote.

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

To include untracked (new) files change the workflow to use the following.

          git add -A
git commit -m "Automated report"

The above workflow should work for the majority of events. For on: pull_request workflows the merging branch (GITHUB_HEAD_REF) should be checked out to replace the default merge commit.

Important: If you have other pull request checks besides the following workflow then you must use a Personal Access Token instead of the default GITHUB_TOKEN. This is due to a deliberate limitation imposed by GitHub Actions that events raised by a workflow (such as push) cannot trigger further workflow runs. This is to prevent accidental "infinite loop" situations, and as an anti-abuse measure. Using a repo scoped Personal Access Token is an approved workaround. See this GitHub issue for further detail on the workaround.

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.GITHUB_TOKEN }}@github.com/$\{\{ github.repository }}
git commit -am "Automated report"
git push

For further examples of push to origin during an on: pull_request workflow see this blog post, GitHub Actions: How to Automate Code Formatting in Pull Requests.

All the provided answers are correct. But I would like to add a bit more to these answers. There can be situations where there are no changes in files. So in that situation, when trying to execute the git commit command it returns an error that fails the GitHub workflow (failed workflows block the PR merge). So we have to check whether there are any changes in files before commit.

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

The above workflow is an example for creating configuration files using jsonnet and GitHub workflow. It first installs jsonnet and runs a python script that creates the config files using jsonnet templates. As mentioned above there can be situation where there are no file changes. So it uses git status command to check whether there are any file changes. (Instead of git status, git diff can also be used. But it wont show untracked files). Rest of the git commands run only if there are file changes.

Also note that I had to use ref: $\{\{ github.head_ref }} to checkout to source branch even though I used checkout@v2 (still detached head problem exists in my case)

All great responses, however I should note that there is a GitHub Action Add & Commit that substantially simplifies the process.

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@v8
with:
author_name: Your Name
author_email: mail@example.com
message: 'Your commit message'
add: 'report.txt'

For auto commit without defining user or anything use EndBug/add-and-commit@v7. Here's my workflow file for auto formatting and commiting js and 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




Here is an example of how to use the official 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