Add create_branch option to force create a new branch (#203)

* Add create_branch option

* Checkout new branch if create_branch input is true

* Add tests

* Update README
This commit is contained in:
Stefan Zweifel 2022-02-27 07:52:17 +01:00 committed by GitHub
parent dee58f4213
commit ebe77391c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 287 additions and 17 deletions

View File

@ -28,15 +28,16 @@ The following is an extended example with all possible options available for thi
```yaml ```yaml
- uses: stefanzweifel/git-auto-commit-action@v4 - uses: stefanzweifel/git-auto-commit-action@v4
with: with:
# Optional, but recommended # Optional. Commit message for the created commit.
# Defaults to "Apply automatic changes" # Defaults to "Apply automatic changes"
commit_message: Automated Change commit_message: Automated Change
# Optional branch name where commit should be pushed to. # Optional. Local and remote branch name where commit is going to be pushed
# Defaults to the current branch. # to. Defaults to the current branch.
# You might need to set `create_branch: true` if the branch does not exist.
branch: feature-123 branch: feature-123
# Optional. Used by `git-commit`. # Optional. Options used by `git-commit`.
# See https://git-scm.com/docs/git-commit#_options # See https://git-scm.com/docs/git-commit#_options
commit_options: '--no-verify --signoff' commit_options: '--no-verify --signoff'
@ -47,8 +48,8 @@ The following is an extended example with all possible options available for thi
# - https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefpathspecapathspec # - https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefpathspecapathspec
file_pattern: src/*.js tests/*.js *.php file_pattern: src/*.js tests/*.js *.php
# Optional local file path to the repository # Optional. Local file path to the repository.
# Defaults to the root of the repository # Defaults to the root of the repository.
repository: . repository: .
# Optional commit user and author settings # Optional commit user and author settings
@ -56,19 +57,19 @@ The following is an extended example with all possible options available for thi
commit_user_email: my-github-actions-bot@example.org # defaults to "actions@github.com" commit_user_email: my-github-actions-bot@example.org # defaults to "actions@github.com"
commit_author: Author <actions@github.com> # defaults to author of the commit that triggered the run commit_author: Author <actions@github.com> # defaults to author of the commit that triggered the run
# Optional tag message # Optional. Tag name being created in the local repository and
# Action will create and push a new tag to the remote repository and the defined branch # pushed to remtoe repository and defined branch.
tagging_message: 'v1.0.0' tagging_message: 'v1.0.0'
# Optional. Used by `git-status` # Optional. Option used by `git-status` to determine if the repository is
# See https://git-scm.com/docs/git-status#_options # dirty. See https://git-scm.com/docs/git-status#_options
status_options: '--untracked-files=no' status_options: '--untracked-files=no'
# Optional. Used by `git-add` # Optional. Options used by `git-add`.
# See https://git-scm.com/docs/git-add#_options # See https://git-scm.com/docs/git-add#_options
add_options: '-u' add_options: '-u'
# Optional. Used by `git-push` # Optional. Options used by `git-push`.
# See https://git-scm.com/docs/git-push#_options # See https://git-scm.com/docs/git-push#_options
push_options: '--force' push_options: '--force'
@ -84,6 +85,9 @@ The following is an extended example with all possible options available for thi
# Optional. Prevents the shell from expanding filenames. # Optional. Prevents the shell from expanding filenames.
# Details: https://www.gnu.org/software/bash/manual/html_node/Filename-Expansion.html # Details: https://www.gnu.org/software/bash/manual/html_node/Filename-Expansion.html
disable_globbing: true disable_globbing: true
# Optional. Create given branch name in local and remote repository.
create_branch: true
``` ```
Please note that the Action depends on `bash`. If you're using the Action in a job in combination with a custom Docker container, make sure that `bash` is installed. Please note that the Action depends on `bash`. If you're using the Action in a job in combination with a custom Docker container, make sure that `bash` is installed.

View File

@ -25,7 +25,7 @@ inputs:
required: false required: false
default: '' default: ''
file_pattern: file_pattern:
description: File pattern used for `git add`. For example `src/\*.js` description: File pattern used for `git add`. For example `src/*.js`
required: false required: false
default: '.' default: '.'
repository: repository:
@ -67,6 +67,9 @@ inputs:
disable_globbing: disable_globbing:
description: Stop the shell from expanding filenames (https://www.gnu.org/software/bash/manual/html_node/Filename-Expansion.html) description: Stop the shell from expanding filenames (https://www.gnu.org/software/bash/manual/html_node/Filename-Expansion.html)
default: false default: false
create_branch:
description: Create new branch with the name of `branch`-input in local and remote repository, if it doesn't exist yet.
default: false
outputs: outputs:
changes_detected: changes_detected:

View File

@ -48,19 +48,25 @@ _switch_to_branch() {
echo "INPUT_BRANCH value: $INPUT_BRANCH"; echo "INPUT_BRANCH value: $INPUT_BRANCH";
# Fetch remote to make sure that repo can be switched to the right branch. # Fetch remote to make sure that repo can be switched to the right branch.
if "$INPUT_SKIP_FETCH"; then if "$INPUT_SKIP_FETCH"; then
echo "::debug::git-fetch has not been executed"; echo "::debug::git-fetch has not been executed";
else else
git fetch --depth=1; git fetch --depth=1;
fi fi
# If `skip_checkout`-input is true, skip the entire checkout step.
if "$INPUT_SKIP_CHECKOUT"; then if "$INPUT_SKIP_CHECKOUT"; then
echo "::debug::git-checkout has not been executed"; echo "::debug::git-checkout has not been executed";
else else
# Switch to branch from current Workflow run # Create new local branch if `create_branch`-input is true
# shellcheck disable=SC2086 if "$INPUT_CREATE_BRANCH"; then
git checkout $INPUT_BRANCH --; # shellcheck disable=SC2086
git checkout -B $INPUT_BRANCH --;
else
# Switch to branch from current Workflow run
# shellcheck disable=SC2086
git checkout $INPUT_BRANCH --;
fi
fi fi
} }

View File

@ -26,6 +26,7 @@ setup() {
export INPUT_SKIP_FETCH=false export INPUT_SKIP_FETCH=false
export INPUT_SKIP_CHECKOUT=false export INPUT_SKIP_CHECKOUT=false
export INPUT_DISABLE_GLOBBING=false export INPUT_DISABLE_GLOBBING=false
export INPUT_CREATE_BRANCH=false
# Configure Git # Configure Git
if [[ -z $(git config user.name) ]]; then if [[ -z $(git config user.name) ]]; then
@ -533,3 +534,259 @@ git_auto_commit() {
assert_line "::set-output name=changes_detected::true" assert_line "::set-output name=changes_detected::true"
assert_line "::debug::Push commit to remote branch dev" assert_line "::debug::Push commit to remote branch dev"
} }
@test "script fails to push commit to new branch that does not exist yet" {
INPUT_BRANCH="not-existend-branch"
INPUT_CREATE_BRANCH=false
run git branch
refute_line --partial "not-existend-branch"
run git branch -r
refute_line --partial "origin/not-existend-branch"
touch "${FAKE_LOCAL_REPOSITORY}"/new-file-{1,2,3}.txt
run git_auto_commit
assert_failure
assert_line "INPUT_REPOSITORY value: ${INPUT_REPOSITORY}"
assert_line "::set-output name=changes_detected::true"
assert_line "INPUT_BRANCH value: not-existend-branch"
assert_line "fatal: invalid reference: not-existend-branch"
run git branch
refute_line --partial "not-existend-branch"
run git branch -r
refute_line --partial "origin/not-existend-branch"
}
@test "It creates new local branch and pushes the new branch to remote" {
INPUT_BRANCH="not-existend-branch"
INPUT_CREATE_BRANCH=true
run git branch
refute_line --partial "not-existend-branch"
run git branch -r
refute_line --partial "origin/not-existend-branch"
touch "${FAKE_LOCAL_REPOSITORY}"/new-file-{1,2,3}.txt
run git_auto_commit
assert_success
assert_line "INPUT_REPOSITORY value: ${INPUT_REPOSITORY}"
assert_line "::set-output name=changes_detected::true"
assert_line -e "::set-output name=commit_hash::[0-9a-f]{40}$"
assert_line "INPUT_BRANCH value: not-existend-branch"
assert_line "INPUT_FILE_PATTERN: ."
assert_line "INPUT_COMMIT_OPTIONS: "
assert_line "::debug::Apply commit options "
assert_line "INPUT_TAGGING_MESSAGE: "
assert_line "No tagging message supplied. No tag will be added."
assert_line "INPUT_PUSH_OPTIONS: "
assert_line "::debug::Apply push options "
assert_line "::debug::Push commit to remote branch not-existend-branch"
run git branch
assert_line --partial "not-existend-branch"
run git branch -r
assert_line --partial "origin/not-existend-branch"
}
@test "it does not create new local branch if local branch already exists" {
git checkout -b not-existend-remote-branch
git checkout master
INPUT_BRANCH="not-existend-remote-branch"
INPUT_CREATE_BRANCH=true
run git branch
assert_line --partial "not-existend-remote-branch"
run git branch -r
refute_line --partial "origin/not-existend-remote-branch"
touch "${FAKE_LOCAL_REPOSITORY}"/new-file-{1,2,3}.txt
run git_auto_commit
assert_success
assert_line "INPUT_REPOSITORY value: ${INPUT_REPOSITORY}"
assert_line "::set-output name=changes_detected::true"
assert_line -e "::set-output name=commit_hash::[0-9a-f]{40}$"
assert_line "INPUT_BRANCH value: not-existend-remote-branch"
assert_line "INPUT_FILE_PATTERN: ."
assert_line "INPUT_COMMIT_OPTIONS: "
assert_line "::debug::Apply commit options "
assert_line "INPUT_TAGGING_MESSAGE: "
assert_line "No tagging message supplied. No tag will be added."
assert_line "INPUT_PUSH_OPTIONS: "
assert_line "::debug::Apply push options "
assert_line "::debug::Push commit to remote branch not-existend-remote-branch"
run git branch
assert_line --partial "not-existend-remote-branch"
run git branch -r
assert_line --partial "origin/not-existend-remote-branch"
}
@test "it creates new local branch and pushes branch to remote even if the remote branch already exists" {
# Create `existing-remote-branch` on remote with changes the local repository does not yet have
cd $FAKE_TEMP_LOCAL_REPOSITORY;
git checkout -b "existing-remote-branch"
touch new-branch-file.txt
git add new-branch-file.txt
git commit -m "Add additional file";
git push origin existing-remote-branch;
run git branch;
assert_line --partial "existing-remote-branch"
# ---------
# Switch to our regular local repository and run `git-auto-commit`
cd $FAKE_LOCAL_REPOSITORY;
INPUT_BRANCH="existing-remote-branch"
INPUT_CREATE_BRANCH=true
run git branch
refute_line --partial "existing-remote-branch"
run git fetch --all;
run git pull origin existing-remote-branch;
run git branch -r;
assert_line --partial "origin/existing-remote-branch"
touch "${FAKE_LOCAL_REPOSITORY}"/new-file-{1,2,3}.txt
run git_auto_commit
assert_success
assert_line "INPUT_REPOSITORY value: ${INPUT_REPOSITORY}"
assert_line "::set-output name=changes_detected::true"
assert_line -e "::set-output name=commit_hash::[0-9a-f]{40}$"
assert_line "INPUT_BRANCH value: existing-remote-branch"
assert_line "INPUT_FILE_PATTERN: ."
assert_line "INPUT_COMMIT_OPTIONS: "
assert_line "::debug::Apply commit options "
assert_line "INPUT_TAGGING_MESSAGE: "
assert_line "No tagging message supplied. No tag will be added."
assert_line "INPUT_PUSH_OPTIONS: "
assert_line "::debug::Apply push options "
assert_line "::debug::Push commit to remote branch existing-remote-branch"
run git branch
assert_line --partial "existing-remote-branch"
run git branch -r
assert_line --partial "origin/existing-remote-branch"
# Assert that branch "existing-remote-branch" was updated on remote
current_sha="$(git rev-parse --verify --short existing-remote-branch)"
remote_sha="$(git rev-parse --verify --short origin/existing-remote-branch)"
assert_equal $current_sha $remote_sha;
}
@test "script fails if new local branch is checked out and push fails as remote has newer commits than local" {
# Create `existing-remote-branch` on remote with changes the local repository does not yet have
cd $FAKE_TEMP_LOCAL_REPOSITORY;
git checkout -b "existing-remote-branch"
touch new-branch-file.txt
git add new-branch-file.txt
git commit -m "Add additional file";
git push origin existing-remote-branch;
run git branch;
assert_line --partial "existing-remote-branch"
# ---------
# Switch to our regular local repository and run `git-auto-commit`
cd $FAKE_LOCAL_REPOSITORY;
INPUT_BRANCH="existing-remote-branch"
INPUT_CREATE_BRANCH=true
run git branch
refute_line --partial "existing-remote-branch"
run git fetch --all;
run git branch -r;
assert_line --partial "origin/existing-remote-branch"
touch "${FAKE_LOCAL_REPOSITORY}"/new-file-{1,2,3}.txt
run git_auto_commit
assert_failure
assert_line "hint: Updates were rejected because the tip of your current branch is behind"
# Assert that branch exists locally and on remote
run git branch
assert_line --partial "existing-remote-branch"
run git branch -r
assert_line --partial "origin/existing-remote-branch"
# Assert that branch "existing-remote-branch" was not updated on remote
current_sha="$(git rev-parse --verify --short existing-remote-branch)"
remote_sha="$(git rev-parse --verify --short origin/existing-remote-branch)"
refute [assert_equal $current_sha $remote_sha];
}
@test "It pushes commit to remote if branch already exists and local repo is behind its remote counterpart" {
# Create `new-branch` on remote with changes the local repository does not yet have
cd $FAKE_TEMP_LOCAL_REPOSITORY;
git checkout -b "new-branch"
touch new-branch-file.txt
git add new-branch-file.txt
git commit --quiet -m "Add additional file";
git push origin new-branch;
run git branch -r
assert_line --partial "origin/new-branch"
# ---------
# Switch to our regular local repository and run `git-auto-commit`
cd $FAKE_LOCAL_REPOSITORY;
INPUT_BRANCH="new-branch"
# Assert that local remote does not know have "new-branch" locally nor does
# know about the remote branch.
run git branch
refute_line --partial "new-branch"
run git branch -r
refute_line --partial "origin/new-branch"
touch "${FAKE_LOCAL_REPOSITORY}"/new-file-{1,2,3}.txt
run git_auto_commit
assert_success
assert_line "INPUT_BRANCH value: new-branch"
assert_line --partial "::debug::Push commit to remote branch new-branch"
# Assert that branch "new-branch" was updated on remote
current_sha="$(git rev-parse --verify --short new-branch)"
remote_sha="$(git rev-parse --verify --short origin/new-branch)"
assert_equal $current_sha $remote_sha;
}