Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add create_branch option to force create a new branch #203

Merged
merged 8 commits into from Feb 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 16 additions & 12 deletions README.md
Expand Up @@ -28,15 +28,16 @@ The following is an extended example with all possible options available for thi
```yaml
- uses: stefanzweifel/git-auto-commit-action@v4
with:
# Optional, but recommended
# Optional. Commit message for the created commit.
# Defaults to "Apply automatic changes"
commit_message: Automated Change

# Optional branch name where commit should be pushed to.
# Defaults to the current branch.
# Optional. Local and remote branch name where commit is going to be pushed
# to. Defaults to the current branch.
# You might need to set `create_branch: true` if the branch does not exist.
branch: feature-123

# Optional. Used by `git-commit`.
# Optional. Options used by `git-commit`.
# See https://git-scm.com/docs/git-commit#_options
commit_options: '--no-verify --signoff'

Expand All @@ -47,28 +48,28 @@ The following is an extended example with all possible options available for thi
# - https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefpathspecapathspec
file_pattern: src/*.js tests/*.js *.php

# Optional local file path to the repository
# Defaults to the root of the repository
# Optional. Local file path to the repository.
# Defaults to the root of the repository.
repository: .

# Optional commit user and author settings
commit_user_name: My GitHub Actions Bot # defaults to "GitHub Actions"
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

# Optional tag message
# Action will create and push a new tag to the remote repository and the defined branch
# Optional. Tag name being created in the local repository and
# pushed to remtoe repository and defined branch.
tagging_message: 'v1.0.0'

# Optional. Used by `git-status`
# See https://git-scm.com/docs/git-status#_options
# Optional. Option used by `git-status` to determine if the repository is
# dirty. See https://git-scm.com/docs/git-status#_options
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
add_options: '-u'

# Optional. Used by `git-push`
# Optional. Options used by `git-push`.
# See https://git-scm.com/docs/git-push#_options
push_options: '--force'

Expand All @@ -84,6 +85,9 @@ The following is an extended example with all possible options available for thi
# Optional. Prevents the shell from expanding filenames.
# Details: https://www.gnu.org/software/bash/manual/html_node/Filename-Expansion.html
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.
Expand Down
5 changes: 4 additions & 1 deletion action.yml
Expand Up @@ -25,7 +25,7 @@ inputs:
required: false
default: ''
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
default: '.'
repository:
Expand Down Expand Up @@ -67,6 +67,9 @@ inputs:
disable_globbing:
description: Stop the shell from expanding filenames (https://www.gnu.org/software/bash/manual/html_node/Filename-Expansion.html)
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:
changes_detected:
Expand Down
14 changes: 10 additions & 4 deletions entrypoint.sh
Expand Up @@ -48,19 +48,25 @@ _switch_to_branch() {
echo "INPUT_BRANCH value: $INPUT_BRANCH";

# Fetch remote to make sure that repo can be switched to the right branch.

if "$INPUT_SKIP_FETCH"; then
echo "::debug::git-fetch has not been executed";
else
git fetch --depth=1;
fi

# If `skip_checkout`-input is true, skip the entire checkout step.
if "$INPUT_SKIP_CHECKOUT"; then
echo "::debug::git-checkout has not been executed";
else
# Switch to branch from current Workflow run
# shellcheck disable=SC2086
git checkout $INPUT_BRANCH --;
# Create new local branch if `create_branch`-input is true
if "$INPUT_CREATE_BRANCH"; then
# 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
}

Expand Down
257 changes: 257 additions & 0 deletions tests/git-auto-commit.bats
Expand Up @@ -26,6 +26,7 @@ setup() {
export INPUT_SKIP_FETCH=false
export INPUT_SKIP_CHECKOUT=false
export INPUT_DISABLE_GLOBBING=false
export INPUT_CREATE_BRANCH=false

# Configure Git
if [[ -z $(git config user.name) ]]; then
Expand Down Expand Up @@ -533,3 +534,259 @@ git_auto_commit() {
assert_line "::set-output name=changes_detected::true"
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;
}