diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml deleted file mode 100644 index c5faa34..0000000 --- a/.github/workflows/integration-tests.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Integration Tests - -on: push - -jobs: - test-commit-works: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - with: - ref: master - - - name: Create Remote Branch - run: | - git checkout -b ci-test - git push origin ci-test - git checkout master - - - name: Add Files - run: touch {a,b,c}.txt - - - name: Run git-auto-commit - id: "auto-commit-action" - uses: ./ - with: - branch: ci-test - commit_message: Message - - - name: Delete Branch - run: git push -d origin ci-test diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f9cb9b2..206d903 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,13 +9,7 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Install Shell Mock - run: | - git clone https://github.com/capitalone/bash_shell_mock - cd bash_shell_mock - sudo ./install.sh /usr/local - - - name: Install BATS + - name: Install testing dependencies run: yarn install - name: Run Tests diff --git a/.gitignore b/.gitignore index 104a7f9..5358650 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -tests/test_repo -tests/tmpstubs -tests/shellmock.* +tests/test_fake_local_repository +tests/test_fake_remote_repository +tests/test_fake_temp_local_repository yarn.lock diff --git a/README.md b/README.md index fa4a43b..97fec33 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,6 @@ - - - This GitHub Action automatically commits files which have been changed during a Workflow run and pushes the commit back to GitHub. By default, the commit is made in the name of "GitHub Actions" and co-authored by the user that made the last commit. @@ -269,10 +266,18 @@ This is due to limitations set up by GitHub, [commits of this Action do not trig ## Running the tests -The package has tests written in [bats](https://github.com/bats-core/bats-core). You can run them with the following command. +The package has tests written in [bats](https://github.com/bats-core/bats-core). Before you can run the test suite locally, you have to install the dependencies with `npm` or `yarn`. + +```shell +npm install +yarn +``` + +You can run the test suite with `npm` or `yarn`. ```shell npm run test +yarn test ``` ## Versioning diff --git a/entrypoint.sh b/entrypoint.sh index 7361895..73c36d4 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -62,6 +62,11 @@ _local_commit() { # shellcheck disable=SC2206 INPUT_COMMIT_OPTIONS_ARRAY=( $INPUT_COMMIT_OPTIONS ); + echo "INPUT_COMMIT_USER_NAME: ${INPUT_COMMIT_USER_NAME}"; + echo "INPUT_COMMIT_USER_EMAIL: ${INPUT_COMMIT_USER_EMAIL}"; + echo "INPUT_COMMIT_MESSAGE: ${INPUT_COMMIT_MESSAGE}"; + echo "INPUT_COMMIT_AUTHOR: ${INPUT_COMMIT_AUTHOR}"; + git -c user.name="$INPUT_COMMIT_USER_NAME" -c user.email="$INPUT_COMMIT_USER_EMAIL" \ commit -m "$INPUT_COMMIT_MESSAGE" \ --author="$INPUT_COMMIT_AUTHOR" \ diff --git a/package.json b/package.json index 4683c2c..21ea2e2 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,10 @@ { "devDependencies": { - "bats": "^1.1.0" + "bats": "^1.1.0", + "bats-assert": "ztombol/bats-assert", + "bats-support": "ztombol/bats-support" }, "scripts": { - "test": "rm -rf tests/tmpstubs && rm -rf tests/shellmock.* && bats tests" + "test": "bats tests" } } diff --git a/tests/git-auto-commit-mocked.bats b/tests/git-auto-commit-mocked.bats deleted file mode 100644 index b21ebe2..0000000 --- a/tests/git-auto-commit-mocked.bats +++ /dev/null @@ -1,439 +0,0 @@ -#!/usr/bin/env bats - -setup() { - . shellmock - - # Build World - export test_repository="${BATS_TEST_DIRNAME}/test_repo" - - rm -rf "${test_repository}" - mkdir "${test_repository}" - touch "${test_repository}"/{a,b,c}.txt - cd "${test_repository}" - - git init --quiet - git add . > /dev/null 2>&1 - - if [[ -z $(git config user.name) ]]; then - git config --global user.email "test@github.com" - git config --global user.name "Test Suite" - fi - - git commit --quiet -m "Init Repo" - - # Set default INPUT variables - export INPUT_REPOSITORY="${BATS_TEST_DIRNAME}/test_repo" - export INPUT_COMMIT_MESSAGE="Commit Message" - export INPUT_BRANCH="master" - export INPUT_COMMIT_OPTIONS="" - export INPUT_FILE_PATTERN="." - export INPUT_COMMIT_USER_NAME="Test Suite" - export INPUT_COMMIT_USER_EMAIL="test@github.com" - export INPUT_COMMIT_AUTHOR="Test Suite " - export INPUT_TAGGING_MESSAGE="" - export INPUT_PUSH_OPTIONS="" - export INPUT_SKIP_DIRTY_CHECK=false - - skipIfNot "$BATS_TEST_DESCRIPTION" - - if [ -z "$TEST_FUNCTION" ]; then - shellmock_clean - fi -} - -teardown() { - - if [ -z "$TEST_FUNCTION" ]; then - shellmock_clean - fi - - rm -rf "${test_repository}" -} - -main() { - bash "${BATS_TEST_DIRNAME}"/../entrypoint.sh -} - - -@test "clean-repo-prints-nothing-to-commit-message" { - - run main - - [ "$status" -eq 0 ] - [ "${lines[0]}" = "INPUT_REPOSITORY value: ${INPUT_REPOSITORY}" ] - [ "${lines[1]}" = "::set-output name=changes_detected::false" ] - [ "${lines[2]}" = "Working tree clean. Nothing to commit." ] -} - -@test "commit-changed-files-and-push-to-remote" { - - touch "${test_repository}"/new-file-{1,2,3}.txt - - shellmock_expect git --type partial --output " M new-file-1.txt M new-file-2.txt M new-file-3.txt" --match "status" - shellmock_expect git --type exact --match "fetch" - shellmock_expect git --type exact --match "checkout master" - shellmock_expect git --type partial --match "add ." - shellmock_expect git --type partial --match '-c' - shellmock_expect git --type partial --match 'push --set-upstream origin' - - run main - - echo "$output" - - # Success Exit Code - [ "$status" = 0 ] - - [ "${lines[0]}" = "INPUT_REPOSITORY value: ${INPUT_REPOSITORY}" ] - [ "${lines[1]}" = "::set-output name=changes_detected::true" ] - [ "${lines[2]}" = "INPUT_BRANCH value: master" ] - [ "${lines[3]}" = "INPUT_FILE_PATTERN: ." ] - [ "${lines[4]}" = "INPUT_COMMIT_OPTIONS: " ] - [ "${lines[5]}" = "::debug::Apply commit options " ] - [ "${lines[6]}" = "INPUT_TAGGING_MESSAGE: " ] - [ "${lines[7]}" = "No tagging message supplied. No tag will be added." ] - [ "${lines[8]}" = "INPUT_PUSH_OPTIONS: " ] - [ "${lines[9]}" = "::debug::Apply push options " ] - [ "${lines[10]}" = "::debug::Push commit to remote branch master" ] - - - shellmock_verify - [ "${capture[0]}" = "git-stub status -s -- ." ] - [ "${capture[1]}" = "git-stub fetch" ] - [ "${capture[2]}" = "git-stub checkout master" ] - [ "${capture[3]}" = "git-stub add ." ] - [ "${capture[4]}" = "git-stub -c user.name=Test Suite -c user.email=test@github.com commit -m Commit Message --author=Test Suite " ] - [ "${capture[5]}" = "git-stub push --set-upstream origin HEAD:master --tags" ] -} - -@test "skip-dirty-on-clean-repo-failure" { - - INPUT_SKIP_DIRTY_CHECK=true - - shellmock_expect git --type exact --match "status -s ." - shellmock_expect git --type exact --match "fetch" - shellmock_expect git --type exact --match "checkout master" - shellmock_expect git --type exact --match "add ." - shellmock_expect git --type partial --match '-c' - shellmock_expect git --type partial --match 'push origin' - - run main - - echo "$output" - - shellmock_verify - [ "${capture[0]}" = "git-stub status -s -- ." ] - [ "${capture[1]}" = "git-stub fetch" ] - [ "${capture[2]}" = "git-stub checkout master" ] - [ "${capture[3]}" = "git-stub add ." ] - [ "${capture[4]}" = "git-stub -c user.name=Test Suite -c user.email=test@github.com commit -m Commit Message --author=Test Suite " ] - [ "${capture[5]}" = "git-stub push --set-upstream origin HEAD:master --tags" ] - - # Failed Exit Code - [ "$status" -ne 0 ] - - [ "${lines[0]}" = "INPUT_REPOSITORY value: ${INPUT_REPOSITORY}" ] - [ "${lines[1]}" = "::set-output name=changes_detected::true" ] - [ "${lines[2]}" = "INPUT_BRANCH value: master" ] - [ "${lines[3]}" = "INPUT_FILE_PATTERN: ." ] - [ "${lines[4]}" = "INPUT_COMMIT_OPTIONS: " ] - [ "${lines[5]}" = "::debug::Apply commit options " ] -} - -@test "git-add-file-pattern-is-applied" { - - INPUT_FILE_PATTERN="*.txt *.html" - - touch "${test_repository}"/new-file-{1,2}.php - touch "${test_repository}"/new-file-{1,2}.html - - shellmock_expect git --type partial --output " M new-file-1.html M new-file-2.html" --match "status" - shellmock_expect git --type exact --match "fetch" - shellmock_expect git --type exact --match "checkout master" - shellmock_expect git --type partial --match "add" - shellmock_expect git --type partial --match '-c' - shellmock_expect git --type partial --match 'push --set-upstream origin' - - run main - - echo "$output" - - # Success Exit Code - [ "$status" = 0 ] - - [ "${lines[3]}" = "INPUT_FILE_PATTERN: *.txt *.html" ] - [ "${lines[10]}" = "::debug::Push commit to remote branch master" ] - - - shellmock_verify - [ "${capture[0]}" = "git-stub status -s -- a.txt b.txt c.txt new-file-1.html new-file-2.html" ] - [ "${capture[1]}" = "git-stub fetch" ] - [ "${capture[2]}" = "git-stub checkout master" ] - [ "${capture[3]}" = "git-stub add a.txt b.txt c.txt new-file-1.html new-file-2.html" ] - [ "${capture[4]}" = "git-stub -c user.name=Test Suite -c user.email=test@github.com commit -m Commit Message --author=Test Suite " ] - [ "${capture[5]}" = "git-stub push --set-upstream origin HEAD:master --tags" ] -} - -@test "git-commit-options-are-applied" { - - INPUT_COMMIT_OPTIONS="--no-verify --signoff" - - touch "${test_repository}"/new-file-{1,2}.txt - - shellmock_expect git --type partial --output " M new-file-1.txt M new-file-2.txt" --match "status" - shellmock_expect git --type exact --match "fetch" - shellmock_expect git --type exact --match "checkout master" - shellmock_expect git --type partial --match "add" - shellmock_expect git --type partial --match '-c' - shellmock_expect git --type partial --match 'push --set-upstream origin' - - run main - - echo "$output" - - # Success Exit Code - [ "$status" = 0 ] - [ "${lines[4]}" = "INPUT_COMMIT_OPTIONS: --no-verify --signoff" ] - [ "${lines[10]}" = "::debug::Push commit to remote branch master" ] - - shellmock_verify - [ "${capture[0]}" = "git-stub status -s -- ." ] - [ "${capture[1]}" = "git-stub fetch" ] - [ "${capture[2]}" = "git-stub checkout master" ] - [ "${capture[3]}" = "git-stub add ." ] - [ "${capture[4]}" = "git-stub -c user.name=Test Suite -c user.email=test@github.com commit -m Commit Message --author=Test Suite --no-verify --signoff" ] - [ "${capture[5]}" = "git-stub push --set-upstream origin HEAD:master --tags" ] -} - -@test "commit-user-and-author-settings-are-applied" { - - INPUT_COMMIT_USER_NAME="A Single Test" - INPUT_COMMIT_USER_EMAIL="single-test@github.com" - INPUT_COMMIT_AUTHOR="A Single Test " - - touch "${test_repository}"/new-file-{1,2}.txt - - shellmock_expect git --type partial --output " M new-file-1.txt M new-file-2.txt" --match "status" - shellmock_expect git --type exact --match "fetch" - shellmock_expect git --type exact --match "checkout master" - shellmock_expect git --type partial --match "add" - shellmock_expect git --type partial --match '-c' - shellmock_expect git --type partial --match 'push --set-upstream origin' - - run main - - echo "$output" - - # Success Exit Code - [ "$status" = 0 ] - - [ "${lines[10]}" = "::debug::Push commit to remote branch master" ] - - shellmock_verify - [ "${capture[0]}" = "git-stub status -s -- ." ] - [ "${capture[1]}" = "git-stub fetch" ] - [ "${capture[2]}" = "git-stub checkout master" ] - [ "${capture[3]}" = "git-stub add ." ] - [ "${capture[4]}" = "git-stub -c user.name=A Single Test -c user.email=single-test@github.com commit -m Commit Message --author=A Single Test " ] - [ "${capture[5]}" = "git-stub push --set-upstream origin HEAD:master --tags" ] -} - -@test "can-create-tag" { - - INPUT_TAGGING_MESSAGE="v1.0.0" - - touch "${test_repository}"/new-file-{1,2,3}.txt - - shellmock_expect git --type partial --output " M new-file-1.txt M new-file-2.txt M new-file-3.txt" --match "status" - shellmock_expect git --type exact --match "fetch" - shellmock_expect git --type exact --match "checkout master" - shellmock_expect git --type partial --match "add ." - shellmock_expect git --type partial --match '-c' - shellmock_expect git --type partial --match 'push --set-upstream origin' - - run main - - echo "$output" - - # Success Exit Code - [ "$status" = 0 ] - - [ "${lines[6]}" = "INPUT_TAGGING_MESSAGE: v1.0.0" ] - [ "${lines[7]}" = "::debug::Create tag v1.0.0" ] - [ "${lines[10]}" = "::debug::Push commit to remote branch master" ] - - - shellmock_verify - [ "${capture[0]}" = "git-stub status -s -- ." ] - [ "${capture[1]}" = "git-stub fetch" ] - [ "${capture[2]}" = "git-stub checkout master" ] - [ "${capture[3]}" = "git-stub add ." ] - [ "${capture[4]}" = "git-stub -c user.name=Test Suite -c user.email=test@github.com commit -m Commit Message --author=Test Suite " ] - [ "${capture[5]}" = "git-stub -c user.name=Test Suite -c user.email=test@github.com tag -a v1.0.0 -m v1.0.0" ] - [ "${capture[6]}" = "git-stub push --set-upstream origin HEAD:master --tags" ] - -} - -@test "git-push-options-are-applied" { - - INPUT_PUSH_OPTIONS="--force" - - touch "${test_repository}"/new-file-{1,2,3}.txt - - shellmock_expect git --type partial --output " M new-file-1.txt M new-file-2.txt M new-file-3.txt" --match "status" - shellmock_expect git --type exact --match "fetch" - shellmock_expect git --type exact --match "checkout master" - shellmock_expect git --type partial --match "add ." - shellmock_expect git --type partial --match '-c' - shellmock_expect git --type partial --match 'push --set-upstream origin' - - run main - - echo "$output" - - # Success Exit Code - [ "$status" = 0 ] - - [ "${lines[8]}" = "INPUT_PUSH_OPTIONS: --force" ] - [ "${lines[9]}" = "::debug::Apply push options --force" ] - [ "${lines[10]}" = "::debug::Push commit to remote branch master" ] - - - shellmock_verify - [ "${capture[0]}" = "git-stub status -s -- ." ] - [ "${capture[1]}" = "git-stub fetch" ] - [ "${capture[2]}" = "git-stub checkout master" ] - [ "${capture[3]}" = "git-stub add ." ] - [ "${capture[4]}" = "git-stub -c user.name=Test Suite -c user.email=test@github.com commit -m Commit Message --author=Test Suite " ] - [ "${capture[5]}" = "git-stub push --set-upstream origin HEAD:master --tags --force" ] - -} - -@test "can-checkout-different-branch" { - - INPUT_BRANCH="foo" - - touch "${test_repository}"/new-file-{1,2,3}.txt - - shellmock_expect git --type partial --output " M new-file-1.txt M new-file-2.txt M new-file-3.txt" --match "status" - shellmock_expect git --type exact --match "fetch" - shellmock_expect git --type exact --match "checkout foo" - shellmock_expect git --type partial --match "add ." - shellmock_expect git --type partial --match '-c' - shellmock_expect git --type partial --match 'push --set-upstream origin' - - run main - - echo "$output" - - # Success Exit Code - [ "$status" = 0 ] - - [ "${lines[0]}" = "INPUT_REPOSITORY value: ${INPUT_REPOSITORY}" ] - [ "${lines[1]}" = "::set-output name=changes_detected::true" ] - [ "${lines[2]}" = "INPUT_BRANCH value: foo" ] - [ "${lines[3]}" = "INPUT_FILE_PATTERN: ." ] - [ "${lines[4]}" = "INPUT_COMMIT_OPTIONS: " ] - [ "${lines[5]}" = "::debug::Apply commit options " ] - [ "${lines[6]}" = "INPUT_TAGGING_MESSAGE: " ] - [ "${lines[7]}" = "No tagging message supplied. No tag will be added." ] - [ "${lines[8]}" = "INPUT_PUSH_OPTIONS: " ] - [ "${lines[9]}" = "::debug::Apply push options " ] - [ "${lines[10]}" = "::debug::Push commit to remote branch foo" ] - - - shellmock_verify - [ "${capture[0]}" = "git-stub status -s -- ." ] - [ "${capture[1]}" = "git-stub fetch" ] - [ "${capture[2]}" = "git-stub checkout foo" ] - [ "${capture[3]}" = "git-stub add ." ] - [ "${capture[4]}" = "git-stub -c user.name=Test Suite -c user.email=test@github.com commit -m Commit Message --author=Test Suite " ] - [ "${capture[5]}" = "git-stub push --set-upstream origin HEAD:foo --tags" ] - -} - -@test "can-work-with-empty-branch-name" { - - INPUT_BRANCH="" - - touch "${test_repository}"/new-file-{1,2,3}.txt - - shellmock_expect git --type partial --output " M new-file-1.txt M new-file-2.txt M new-file-3.txt" --match "status" - shellmock_expect git --type exact --match "fetch" - shellmock_expect git --type exact --match "checkout" - shellmock_expect git --type partial --match "add ." - shellmock_expect git --type partial --match '-c' - shellmock_expect git --type partial --match 'push origin' - - run main - - echo "$output" - - # Success Exit Code - [ "$status" = 0 ] - - [ "${lines[0]}" = "INPUT_REPOSITORY value: ${INPUT_REPOSITORY}" ] - [ "${lines[1]}" = "::set-output name=changes_detected::true" ] - [ "${lines[2]}" = "INPUT_BRANCH value: " ] - [ "${lines[3]}" = "INPUT_FILE_PATTERN: ." ] - [ "${lines[4]}" = "INPUT_COMMIT_OPTIONS: " ] - [ "${lines[5]}" = "::debug::Apply commit options " ] - [ "${lines[6]}" = "INPUT_TAGGING_MESSAGE: " ] - [ "${lines[7]}" = "No tagging message supplied. No tag will be added." ] - [ "${lines[8]}" = "INPUT_PUSH_OPTIONS: " ] - [ "${lines[9]}" = "::debug::Apply push options " ] - [ "${lines[10]}" = "::debug::git push origin" ] - - - shellmock_verify - [ "${capture[0]}" = "git-stub status -s -- ." ] - [ "${capture[1]}" = "git-stub fetch" ] - [ "${capture[2]}" = "git-stub checkout" ] - [ "${capture[3]}" = "git-stub add ." ] - [ "${capture[4]}" = "git-stub -c user.name=Test Suite -c user.email=test@github.com commit -m Commit Message --author=Test Suite " ] - [ "${capture[5]}" = "git-stub push origin" ] -} - -@test "can-work-with-empty-branch-name-and-tags" { - - INPUT_BRANCH="" - INPUT_TAGGING_MESSAGE="v2.0.0" - - touch "${test_repository}"/new-file-{1,2,3}.txt - - shellmock_expect git --type partial --output " M new-file-1.txt M new-file-2.txt M new-file-3.txt" --match "status" - shellmock_expect git --type exact --match "fetch" - shellmock_expect git --type exact --match "checkout" - shellmock_expect git --type partial --match "add ." - shellmock_expect git --type partial --match '-c' - shellmock_expect git --type partial --match 'push origin' - - run main - - echo "$output" - - # Success Exit Code - [ "$status" = 0 ] - - [ "${lines[0]}" = "INPUT_REPOSITORY value: ${INPUT_REPOSITORY}" ] - [ "${lines[1]}" = "::set-output name=changes_detected::true" ] - [ "${lines[2]}" = "INPUT_BRANCH value: " ] - [ "${lines[3]}" = "INPUT_FILE_PATTERN: ." ] - [ "${lines[4]}" = "INPUT_COMMIT_OPTIONS: " ] - [ "${lines[5]}" = "::debug::Apply commit options " ] - [ "${lines[6]}" = "INPUT_TAGGING_MESSAGE: v2.0.0" ] - [ "${lines[7]}" = "::debug::Create tag v2.0.0" ] - [ "${lines[8]}" = "INPUT_PUSH_OPTIONS: " ] - [ "${lines[9]}" = "::debug::Apply push options " ] - [ "${lines[10]}" = "::debug::git push origin --tags" ] - - - shellmock_verify - [ "${capture[0]}" = "git-stub status -s -- ." ] - [ "${capture[1]}" = "git-stub fetch" ] - [ "${capture[2]}" = "git-stub checkout" ] - [ "${capture[3]}" = "git-stub add ." ] - [ "${capture[4]}" = "git-stub -c user.name=Test Suite -c user.email=test@github.com commit -m Commit Message --author=Test Suite " ] - [ "${capture[5]}" = "git-stub -c user.name=Test Suite -c user.email=test@github.com tag -a v2.0.0 -m v2.0.0" ] - [ "${capture[6]}" = "git-stub push origin --tags" ] - -} diff --git a/tests/git-auto-commit.bats b/tests/git-auto-commit.bats new file mode 100644 index 0000000..ee381a9 --- /dev/null +++ b/tests/git-auto-commit.bats @@ -0,0 +1,299 @@ +#!/usr/bin/env bats + +load '../node_modules/bats-support/load' +load '../node_modules/bats-assert/load' + +setup() { + # Define Paths for local repository used during tests + export FAKE_LOCAL_REPOSITORY="${BATS_TEST_DIRNAME}/test_fake_local_repository" + export FAKE_REMOTE="${BATS_TEST_DIRNAME}/test_fake_remote_repository" + export FAKE_TEMP_LOCAL_REPOSITORY="${BATS_TEST_DIRNAME}/test_fake_temp_local_repository" + + # Set default INPUT variables used by the GitHub Action + export INPUT_REPOSITORY="${FAKE_LOCAL_REPOSITORY}" + export INPUT_COMMIT_MESSAGE="Commit Message" + export INPUT_BRANCH="master" + export INPUT_COMMIT_OPTIONS="" + export INPUT_FILE_PATTERN="." + export INPUT_COMMIT_USER_NAME="Test Suite" + export INPUT_COMMIT_USER_EMAIL="test@github.com" + export INPUT_COMMIT_AUTHOR="Test Suite " + export INPUT_TAGGING_MESSAGE="" + export INPUT_PUSH_OPTIONS="" + export INPUT_SKIP_DIRTY_CHECK=false + + # Configure Git + if [[ -z $(git config user.name) ]]; then + git config --global user.name "Test Suite" + git config --global user.email "test@github.com" + fi + + # Create and setup some fake repositories for testing + _setup_fake_remote_repository + _setup_local_repository +} + +teardown() { + rm -rf "${FAKE_LOCAL_REPOSITORY}" + rm -rf "${FAKE_REMOTE}" + rm -rf "${FAKE_TEMP_LOCAL_REPOSITORY}" +} + +# Create a fake remote repository which tests can push against +_setup_fake_remote_repository() { + # Create the bare repository, which will act as our remote/origin + rm -rf "${FAKE_REMOTE}"; + mkdir "${FAKE_REMOTE}"; + cd "${FAKE_REMOTE}"; + git init --bare; + + # Clone the remote repository to a temporary location. + rm -rf "${FAKE_TEMP_LOCAL_REPOSITORY}" + git clone "${FAKE_REMOTE}" "${FAKE_TEMP_LOCAL_REPOSITORY}" + + # Create some files, commit them and push them to the remote repository + touch "${FAKE_TEMP_LOCAL_REPOSITORY}"/remote-files{1,2,3}.txt + cd "${FAKE_TEMP_LOCAL_REPOSITORY}"; + git add .; + git commit --quiet -m "Init Remote Repository"; + git push origin master; +} + +# Clone our fake remote repository and set it up for testing +_setup_local_repository() { + # Clone remote repository. In this repository we will do our testing + rm -rf "${FAKE_LOCAL_REPOSITORY}" + git clone "${FAKE_REMOTE}" "${FAKE_LOCAL_REPOSITORY}" + + cd "${FAKE_LOCAL_REPOSITORY}"; +} + +# Run the main code related to this GitHub Action +git_auto_commit() { + bash "${BATS_TEST_DIRNAME}"/../entrypoint.sh +} + +@test "It detects changes, commits them and pushes them to the remote repository" { + 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 "INPUT_BRANCH value: master" + 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 master" +} + +@test "It prints a 'Nothing to commit' message in a clean repository" { + run git_auto_commit + + assert_success + + assert_line "INPUT_REPOSITORY value: ${INPUT_REPOSITORY}" + assert_line "::set-output name=changes_detected::false" + assert_line "Working tree clean. Nothing to commit." +} + +@test "If SKIP_DIRTY_CHECK is set to true on a clean repo it fails to push" { + INPUT_SKIP_DIRTY_CHECK=true + + run git_auto_commit + + assert_failure + + assert_line "INPUT_REPOSITORY value: ${INPUT_REPOSITORY}" + assert_line "::set-output name=changes_detected::true" + + assert_line "::set-output name=changes_detected::true" + assert_line "INPUT_BRANCH value: master" + assert_line "INPUT_FILE_PATTERN: ." + assert_line "INPUT_COMMIT_OPTIONS: " + assert_line "::debug::Apply commit options " +} + +@test "It applies INPUT_FILE_PATTERN when creating commit" { + INPUT_FILE_PATTERN="*.txt *.html" + + touch "${FAKE_LOCAL_REPOSITORY}"/new-file-{1,2}.php + touch "${FAKE_LOCAL_REPOSITORY}"/new-file-{1,2}.html + + run git_auto_commit + + assert_success + + assert_line "INPUT_FILE_PATTERN: *.txt *.html" + assert_line "::debug::Push commit to remote branch master" + + # Assert that PHP files have not been added. + run git status + assert_output --partial 'new-file-1.php' +} + +@test "It applies INPUT_COMMIT_OPTIONS when creating commit" { + INPUT_COMMIT_OPTIONS="--no-verify --signoff" + + touch "${FAKE_LOCAL_REPOSITORY}"/new-file-{1,2}.txt + + run git_auto_commit + + assert_success + + assert_line "INPUT_COMMIT_OPTIONS: --no-verify --signoff" + assert_line "::debug::Push commit to remote branch master" + + # Assert last commit was signed off + run git log -n 1 + assert_output --partial "Signed-off-by:" +} + +@test "It applies commit user and author settings" { + INPUT_COMMIT_USER_NAME="A Single Test" + INPUT_COMMIT_USER_EMAIL="single-test@github.com" + INPUT_COMMIT_AUTHOR="A Single Test " + + touch "${FAKE_LOCAL_REPOSITORY}"/new-file-{1,2}.txt + + run git_auto_commit + + assert_success + + assert_line "INPUT_COMMIT_USER_NAME: A Single Test"; + assert_line "INPUT_COMMIT_USER_EMAIL: single-test@github.com"; + assert_line "INPUT_COMMIT_AUTHOR: A Single Test "; + assert_line "::debug::Push commit to remote branch master" + + # Asser last commit was made by the defined user/author + run git log -1 --pretty=format:'%ae' + assert_output --partial "single@users.noreply.github.com" + + run git log -1 --pretty=format:'%an' + assert_output --partial "A Single Test" + + run git log -1 --pretty=format:'%cn' + assert_output --partial "A Single Test" + + run git log -1 --pretty=format:'%ce' + assert_output --partial "single-test@github.com" +} + +@test "It creates a tag with the commit" { + INPUT_TAGGING_MESSAGE="v1.0.0" + + touch "${FAKE_LOCAL_REPOSITORY}"/new-file-{1,2,3}.txt + + run git_auto_commit + + assert_success + + assert_line "INPUT_TAGGING_MESSAGE: v1.0.0" + assert_line "::debug::Create tag v1.0.0" + assert_line "::debug::Push commit to remote branch master" + + # Assert a tag v1.0.0 has been created + run git tag + assert_output v1.0.0 + + run git ls-remote --tags --refs + assert_output --partial refs/tags/v1.0.0 +} + +@test "It applies INPUT_PUSH_OPTIONS when pushing commit to remote" { + + touch "${FAKE_TEMP_LOCAL_REPOSITORY}"/newer-remote-files{1,2,3}.txt + cd "${FAKE_TEMP_LOCAL_REPOSITORY}"; + git add .; + git commit --quiet -m "Add more remote files"; + git push origin master; + + + INPUT_PUSH_OPTIONS="--force" + + touch "${FAKE_LOCAL_REPOSITORY}"/new-file-{1,2,3}.txt + + run git_auto_commit + + assert_success + + assert_line "INPUT_PUSH_OPTIONS: --force" + assert_line "::debug::Apply push options --force" + assert_line "::debug::Push commit to remote branch master" + + # Assert that the commit has been pushed with --force and + # sha values are equal on local and remote + current_sha="$(git rev-parse --verify --short master)" + remote_sha="$(git rev-parse --verify --short origin/master)" + + assert_equal $current_sha $remote_sha +} + +@test "It can checkout a different branch" { + # Create foo-branch and then immediately switch back to master + git checkout -b foo + git checkout master + + INPUT_BRANCH="foo" + + touch "${FAKE_LOCAL_REPOSITORY}"/new-file-{1,2,3}.txt + + run git_auto_commit + + assert_success + + assert_line "INPUT_BRANCH value: foo" + assert_line "::debug::Push commit to remote branch foo" + + # Assert a new branch "foo" exists on remote + run git ls-remote --heads + assert_output --partial refs/heads/foo +} + +@test "It uses existing branch name when pushing when INPUT_BRANCH is empty" { + INPUT_BRANCH="" + + touch "${FAKE_LOCAL_REPOSITORY}"/new-file-{1,2,3}.txt + + run git_auto_commit + + assert_success + + assert_line "INPUT_BRANCH value: " + assert_line --partial "::debug::git push origin" + + # Assert that branch "master" was updated on remote + current_sha="$(git rev-parse --verify --short master)" + remote_sha="$(git rev-parse --verify --short origin/master)" + + assert_equal $current_sha $remote_sha +} + +@test "It uses existing branch when INPUT_BRANCH is empty and INPUT_TAGGING_MESSAGE is set" { + INPUT_BRANCH="" + INPUT_TAGGING_MESSAGE="v2.0.0" + + touch "${FAKE_LOCAL_REPOSITORY}"/new-file-{1,2,3}.txt + + run git_auto_commit + + assert_success + + assert_line "INPUT_TAGGING_MESSAGE: v2.0.0" + assert_line "::debug::Create tag v2.0.0" + assert_line "::debug::git push origin --tags" + + # Assert a tag v2.0.0 has been created + run git tag + assert_output v2.0.0 + + # Assert tag v2.0.0 has been pushed to remote + run git ls-remote --tags --refs + assert_output --partial refs/tags/v2.0.0 +} diff --git a/yarn.lock b/yarn.lock index d210b2e..1d4ab40 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,14 @@ # yarn lockfile v1 +bats-assert@ztombol/bats-assert: + version "0.3.0" + resolved "https://codeload.github.com/ztombol/bats-assert/tar.gz/9f88b4207da750093baabc4e3f41bf68f0dd3630" + +bats-support@ztombol/bats-support: + version "0.3.0" + resolved "https://codeload.github.com/ztombol/bats-support/tar.gz/004e707638eedd62e0481e8cdc9223ad471f12ee" + bats@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/bats/-/bats-1.2.1.tgz#c15aecc3eb331aedf28678880fab2be0b73eba43"