diff --git a/git-commit/Dockerfile b/git-commit/Dockerfile index 0d7e8b8..7c48d32 100644 --- a/git-commit/Dockerfile +++ b/git-commit/Dockerfile @@ -2,7 +2,7 @@ FROM alpine RUN apk update && \ apk upgrade && \ - apk add git curl jq rsync + apk add git curl jq rsync openssh gnupg ADD ./entrypoint.sh /entrypoint.sh diff --git a/git-commit/README.md b/git-commit/README.md index ff7f4b2..ec4825b 100644 --- a/git-commit/README.md +++ b/git-commit/README.md @@ -14,4 +14,6 @@ | `pr_title` | `"[AUTOMATED] Update files from ${GITHUB_REPOSITORY}"` | `"Pull request title"` | | `pr_description` | `"Triggered by https://github.com/${GITHUB_REPOSITORY}/commit/${GITHUB_SHA}"` | `"Pull request description"` | | `pr_base` | `"master"` | `"Pull request base"` | -| `pr_labels` | `""` | `"Pull request labels separated by comma"` | +| `pr_labels` | `""` | `"Pull request labels separated by comma"` | +| `ssh_private_key`| `""` | `"SSH private key for commit signing"` | +| `gpg_private_key`| `""` | `"GPG private key (armored) for commit signing"` | diff --git a/git-commit/action.yml b/git-commit/action.yml index aac8300..944d146 100644 --- a/git-commit/action.yml +++ b/git-commit/action.yml @@ -33,6 +33,12 @@ inputs: description: "Mark PR with specific labels. Multiple labels separated by comma" required: false default: "" + ssh_private_key: + description: "SSH private key for commit signing. If provided, commits will be signed using SSH" + required: false + gpg_private_key: + description: "GPG private key (armored) for commit signing. If provided, commits will be signed using GPG" + required: false runs: using: "docker" image: "Dockerfile" @@ -47,6 +53,8 @@ runs: - ${{ inputs.pr-description }} - ${{ inputs.pr-base }} - ${{ inputs.pr-labels }} + - ${{ inputs.ssh-private-key }} + - ${{ inputs.gpg-private-key }} branding: icon: "git-commit" color: "green" diff --git a/git-commit/entrypoint.sh b/git-commit/entrypoint.sh index 638d129..1152e24 100755 --- a/git-commit/entrypoint.sh +++ b/git-commit/entrypoint.sh @@ -73,6 +73,24 @@ DEST_DIR=$(mktemp -d) echo "Cloning destination git repository" git config --global user.name "$INPUT_USER_NAME" git config --global user.email "$INPUT_USER_EMAIL" + +if [ -n "$INPUT_GPG_PRIVATE_KEY" ]; then + echo "Configuring GPG commit signing" + echo "$INPUT_GPG_PRIVATE_KEY" | gpg --batch --import + GPG_KEY_ID=$(gpg --list-secret-keys --keyid-format long 2>/dev/null | grep sec | head -1 | sed 's/.*\/\([A-F0-9]*\).*/\1/') + git config --global user.signingkey "$GPG_KEY_ID" + git config --global commit.gpgsign true +elif [ -n "$INPUT_SSH_PRIVATE_KEY" ]; then + echo "Configuring SSH commit signing" + SSH_KEY_FILE="$HOME/.ssh/signing_key" + mkdir -p "$HOME/.ssh" + echo "$INPUT_SSH_PRIVATE_KEY" > "$SSH_KEY_FILE" + chmod 600 "$SSH_KEY_FILE" + git config --global gpg.format ssh + git config --global user.signingkey "$SSH_KEY_FILE" + git config --global commit.gpgsign true +fi + git clone "https://x-access-token:$API_TOKEN_GITHUB@github.com/$INPUT_REPOSITORY.git" "$DEST_DIR" git config --global --add safe.directory "$DEST_DIR" @@ -94,9 +112,13 @@ for INPUT in $INPUT_FILES; do # If it's a file or matches a glob, sync the file rsync -avh "$INPUT" "$DEST_DIR/$(dirname "$INPUT")/" else - # delete file in destination - # https://www.shellcheck.net/wiki/SC2115 - rm -rf "${DEST_DIR:?}/$(dirname "$INPUT")/" + # Source path doesn't exist — delete the exact path in destination (not its parent) + DEST_PATH="${DEST_DIR:?}/$INPUT" + echo "::warning::Path '$INPUT' does not exist in source repository" + if [ -e "$DEST_PATH" ]; then + echo "Removing deleted path: $INPUT" + rm -rf "$DEST_PATH" + fi fi done diff --git a/git-copy/Dockerfile b/git-copy/Dockerfile index da1a3a4..3a9c170 100644 --- a/git-copy/Dockerfile +++ b/git-copy/Dockerfile @@ -2,7 +2,7 @@ FROM alpine RUN apk update && \ apk upgrade && \ - apk add git curl jq + apk add git curl jq openssh gnupg ADD ./entrypoint.sh /entrypoint.sh diff --git a/git-copy/action.yml b/git-copy/action.yml index 2a222a1..74b7b31 100644 --- a/git-copy/action.yml +++ b/git-copy/action.yml @@ -39,6 +39,12 @@ inputs: description: 'Mark PR with specific labels. Multiple labels separated by comma' required: false default: '' + ssh_private_key: + description: 'SSH private key for commit signing. If provided, commits will be signed using SSH' + required: false + gpg_private_key: + description: 'GPG private key (armored) for commit signing. If provided, commits will be signed using GPG' + required: false runs: using: 'docker' image: 'Dockerfile' @@ -55,6 +61,8 @@ runs: - ${{ inputs.pr-description }} - ${{ inputs.pr-base }} - ${{ inputs.pr_labels }} + - ${{ inputs.ssh-private-key }} + - ${{ inputs.gpg-private-key }} branding: icon: 'git-commit' color: 'green' \ No newline at end of file diff --git a/git-copy/entrypoint.sh b/git-copy/entrypoint.sh index cc9c914..c2684b6 100755 --- a/git-copy/entrypoint.sh +++ b/git-copy/entrypoint.sh @@ -77,6 +77,24 @@ CLONE_DIR=$(mktemp -d) echo "Cloning destination git repository github.com/$INPUT_REPOSITORY" git config --global user.name "$INPUT_USER_NAME" git config --global user.email "$INPUT_USER_EMAIL" + +if [ -n "$INPUT_GPG_PRIVATE_KEY" ]; then + echo "Configuring GPG commit signing" + echo "$INPUT_GPG_PRIVATE_KEY" | gpg --batch --import + GPG_KEY_ID=$(gpg --list-secret-keys --keyid-format long 2>/dev/null | grep sec | head -1 | sed 's/.*\/\([A-F0-9]*\).*/\1/') + git config --global user.signingkey "$GPG_KEY_ID" + git config --global commit.gpgsign true +elif [ -n "$INPUT_SSH_PRIVATE_KEY" ]; then + echo "Configuring SSH commit signing" + SSH_KEY_FILE="$HOME/.ssh/signing_key" + mkdir -p "$HOME/.ssh" + echo "$INPUT_SSH_PRIVATE_KEY" > "$SSH_KEY_FILE" + chmod 600 "$SSH_KEY_FILE" + git config --global gpg.format ssh + git config --global user.signingkey "$SSH_KEY_FILE" + git config --global commit.gpgsign true +fi + git clone "https://x-access-token:$API_TOKEN_GITHUB@github.com/$INPUT_REPOSITORY.git" "$CLONE_DIR" --branch "${INPUT_PR_BASE}" BASE_DIR=$(pwd)