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

Improve new commit check and fix 'first sync' shallow issue #38

Merged
merged 9 commits into from
Nov 26, 2021
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ An action with forks in mind! Automatically sync a branch on your fork with the

**Bonus:** This action can also sync between branches on any two repositories. So you have options. :slightly_smiling_face:

**\*\*FIXED in v3.1:\*\*** Git config values are now set only if they haven't been set elsewhere by other actions in a workflow. This was done to avoid conflict setting config values in other job steps (like [gpg commit signing](https://github.com/aormsby/Fork-Sync-With-Upstream-action/wiki/GPG-Signing))
**\*\*FIXED in v3.2:\*\*** Checking for new commits to sync has been improved to better support active development branches. Instead of only comparing head SHA values, it does a deeper hash comparison between the target and upstream branches since the last action run. Length of time is based on new input var `shallow_since`, which defaults to `1 month ago`. ([wiki](https://github.com/aormsby/Fork-Sync-With-Upstream-action/wiki/Configuration#advanced-use))

**\*\*NEW in v3:\*\*** Test Mode runs key checks on your input values to help you verify your action configuration before running and avoid errors when you go live! ([wiki](https://github.com/aormsby/Fork-Sync-With-Upstream-action/wiki#test-mode))

Expand Down Expand Up @@ -47,16 +47,19 @@ This action supports syncing from both public and private upstream repos. Store

#### Advanced Use (all optional args)

| Name | Required? | Default | Example |
| --------------------------- | :----------------: | --------------------------- | -------------------------- |
| host_domain | :white_check_mark: | 'github.com' | 'github.com' |
| target_branch_checkout_args | | | '--recurse-submodules' |
| git_log_format_args | | '--pretty=oneline' | '--graph --pretty=oneline' |
| upstream_pull_args | | | '--ff-only --tags' |
| target_branch_push_args | | | '--force' |
| git_config_user | | 'GH Action - Upstream Sync' | |
| git_config_email | | 'action@github.com' | |
| git_config_pull_rebase | | 'false' | |
| Name | Required? | Default | Example |
| --------------------------- | :----------------: | --------------------------- | ----------------------------------- |
| host_domain | :white_check_mark: | 'github.com' | 'github.com' |
| shallow_since | :white_check_mark: | '1 month ago' | '2 days ago', '3 weeks 7 hours ago' |
| target_branch_checkout_args | | | '--recurse-submodules' |
| git_log_format_args | | '--pretty=oneline' | '--graph --pretty=oneline' |
| upstream_pull_args | | | '--ff-only --tags' |
| target_branch_push_args | | | '--force' |
| git_config_user | | 'GH Action - Upstream Sync' | |
| git_config_email | | 'action@github.com' | |
| git_config_pull_rebase | | 'false' | |

`shallow_since` -> Value should match the time between workflow runs to get the history depth required (but no more) for a good check of new commits to sync

##### Git Config Settings

Expand All @@ -75,6 +78,8 @@ Want more output variables? [Open an issue](https://github.com/aormsby/Fork-Sync
## Sample Workflow

```yaml
name: 'Usptream Sync'

on:
schedule:
- cron: '0 7 * * 1,4'
Expand Down Expand Up @@ -103,7 +108,7 @@ jobs:
# Step 2: run the sync action
- name: Sync upstream changes
id: sync
uses: aormsby/Fork-Sync-With-Upstream-action@v3.1
uses: aormsby/Fork-Sync-With-Upstream-action@v3.2
with:
target_sync_branch: my-branch
# REQUIRED 'target_repo_token' exactly like this!
Expand Down
5 changes: 5 additions & 0 deletions action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ inputs:
required: true
default: 'github.com'

shallow_since:
description: 'Length of time used when fetching shallow repo data, should match how often you perform a sync'
required: true
default: '1 month ago'

outputs:
has_new_commits:
description: 'true when new commits were included in this sync'
Expand Down
7 changes: 2 additions & 5 deletions entry/run_action.sh
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
#!/bin/sh

# shellcheck disable=SC1091
# source action scripts, then run individual functions

# shellcheck disable=SC1091
# config git settings
. "${ACTION_PARENT_DIR}"/run/config_git.sh
config_for_action

# shellcheck disable=SC1091
# checkout target branch in target repo
. "${ACTION_PARENT_DIR}"/run/checkout_branch.sh
checkout

# shellcheck disable=SC1091
# set upstream repo
. "${ACTION_PARENT_DIR}"/run/set_upstream_repo.sh
set_upstream

# shellcheck disable=SC1091
# check for new commits and sync or exit
. "${ACTION_PARENT_DIR}"/run/get_updates.sh
check_for_updates
find_last_synced_commit
output_new_commit_list
sync_new_commits

# shellcheck disable=SC1091
# push newly synced commits to local branch
. "${ACTION_PARENT_DIR}"/run/push_updates.sh
push_new_commits
Expand Down
60 changes: 47 additions & 13 deletions run/get_updates.sh
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
#!/bin/sh

# check latest commit hashes for a match, exit if nothing to sync
# shellcheck disable=SC2086

# check latest commit hashes for a match, exit if nothing to sync
check_for_updates() {
write_out -1 'Checking for new commits on upstream branch.\n'

# get latest commit hashes from local and remote branches for comparison
# shellcheck disable=SC2086
git fetch upstream "${INPUT_UPSTREAM_SYNC_BRANCH}"
LOCAL_COMMIT_HASH=$(git rev-parse "${INPUT_TARGET_SYNC_BRANCH}")
# fetch commits from upstream branch within given time frame (default 1 month)
git fetch --quiet --shallow-since="${INPUT_SHALLOW_SINCE}" upstream "${INPUT_UPSTREAM_SYNC_BRANCH}"
COMMAND_STATUS=$?

if [ "${COMMAND_STATUS}" != 0 ]; then
# if shallow fetch fails, no new commits are avilable for sync
HAS_NEW_COMMITS=false
exit_no_commits
fi

UPSTREAM_COMMIT_HASH=$(git rev-parse "upstream/${INPUT_UPSTREAM_SYNC_BRANCH}")

if [ -z "${LOCAL_COMMIT_HASH}" ] || [ -z "${UPSTREAM_COMMIT_HASH}" ]; then
# check is latest upstream hash is in target branch
git fetch --quiet --shallow-since="${INPUT_SHALLOW_SINCE}" origin "${INPUT_TARGET_SYNC_BRANCH}"
BRANCH_WITH_LATEST="$(git branch "${INPUT_TARGET_SYNC_BRANCH}" --contains="${UPSTREAM_COMMIT_HASH}")"

if [ -z "${UPSTREAM_COMMIT_HASH}" ]; then
HAS_NEW_COMMITS="error"
elif [ "${LOCAL_COMMIT_HASH}" = "${UPSTREAM_COMMIT_HASH}" ]; then
elif [ -n "${BRANCH_WITH_LATEST}" ]; then
HAS_NEW_COMMITS=false
else
HAS_NEW_COMMITS=true
Expand All @@ -34,20 +45,43 @@ exit_no_commits() {
write_out 0 'No new commits to sync. Finishing sync action gracefully.'
}

find_last_synced_commit() {
LAST_SYNCED_COMMIT=""
TARGET_BRANCH_LOG="$(git rev-list "${INPUT_TARGET_SYNC_BRANCH}")"
UPSTREAM_BRANCH_LOG="$(git rev-list "upstream/${INPUT_UPSTREAM_SYNC_BRANCH}")"

for hash in ${TARGET_BRANCH_LOG}; do
UPSTREAM_CHECK="$(echo "${UPSTREAM_BRANCH_LOG}" | grep "${hash}")"
if [ -n "${UPSTREAM_CHECK}" ]; then
LAST_SYNCED_COMMIT="${hash}"
break
fi
done
}

# display new commits since last sync
output_new_commit_list() {
write_out -1 '\nNew commits since last sync:'
# shellcheck disable=SC2086
git log upstream/"${INPUT_UPSTREAM_SYNC_BRANCH}" "${LOCAL_COMMIT_HASH}"..HEAD ${INPUT_GIT_LOG_FORMAT_ARGS}
if [ -z "${LAST_SYNCED_COMMIT}" ]; then
write_out -1 "\nNo previous sync found from upstream repo. Syncing entire commit history."
UNSHALLOW=true
else
write_out -1 '\nNew commits since last sync:'
git log upstream/"${INPUT_UPSTREAM_SYNC_BRANCH}" "${LAST_SYNCED_COMMIT}"..HEAD ${INPUT_GIT_LOG_FORMAT_ARGS}
fi
}

# sync from upstream to target_sync_branch
sync_new_commits() {
write_out -1 '\nSyncing new commits...'

# pull_args examples: "--ff-only", "--tags", "--ff-only --tags"
# shellcheck disable=SC2086
git pull --no-edit ${INPUT_UPSTREAM_PULL_ARGS} upstream "${INPUT_UPSTREAM_SYNC_BRANCH}"
if [ "${UNSHALLOW}" = true ]; then
git repack -d upstream "${INPUT_UPSTREAM_SYNC_BRANCH}"
git pull --unshallow --no-edit ${INPUT_UPSTREAM_PULL_ARGS} upstream "${INPUT_UPSTREAM_SYNC_BRANCH}"
else
# pull_args examples: "--ff-only", "--tags", "--ff-only --tags"
git pull --no-edit ${INPUT_UPSTREAM_PULL_ARGS} upstream "${INPUT_UPSTREAM_SYNC_BRANCH}"
fi

COMMAND_STATUS=$?

if [ "${COMMAND_STATUS}" != 0 ]; then
Expand Down