I highly recommend using python-semantic-release instead. It provides full control over the release creation and does not have roadblocks in place preventing you from using it on non-latest commits. Still, if using semantic-release is a must, above scripts provide the means to do so.
Last active
March 19, 2025 18:28
-
-
Save c0m1c5an5/0a1315a135b37b00ba58d07881a1ec6a to your computer and use it in GitHub Desktop.
Git wrapper to allow semantic-release to work when HEAD is behind remote.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env sh | |
# Copyright (c) 2024 Maksym Kondratenko | |
# SPDX-License-Identifier: BSD-3-Clause | |
set -eu | |
git_bin="/usr/bin/git" | |
get_remote() { | |
"${git_bin}" config --get remote.origin.url || : | |
} | |
get_branch() { | |
"${git_bin}" symbolic-ref -q --short HEAD || : | |
} | |
if ! [ -x "${git_bin}" ]; then | |
echo >&2 "ERR: Git binary '${git_bin}' not executable." | |
exit 127 | |
fi | |
if [ "${1:-}" == "ls-remote" ] && | |
[ "${2:-}" == "--heads" ]; then | |
if [ "${3:-}" == "$(get_remote)" ]; then | |
shift 3 | |
exec "${git_bin}" show-ref --heads "${@}" | |
fi | |
elif [ "${1:-}" == "push" ] && | |
[ "${2:-}" == "--dry-run" ] && | |
[ "${3:-}" == "--no-verify" ] && | |
[ "${4:-}" == "$(get_remote)" ] && | |
[ "${5:-}" == "HEAD:$(get_branch)" ]; then | |
exit 0 | |
fi | |
exec "${git_bin}" "${@}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This snippet shows how to use the provided git wrapper | |
# to allow for execution when HEAD is behind remote branch. | |
mkdir -p ~/.local/opt/git-remote-mock | |
wget -O ~/.local/opt/git-remote-mock/git https://gist.githubusercontent.com/c0m1c5an5/0a1315a135b37b00ba58d07881a1ec6a/raw/07064587985e65d80fc3ee717551841330cdf832/git | |
chmod 755 ~/.local/opt/git-remote-mock/git | |
PATH="${HOME}/.local/opt/git-remote-mock:${PATH}" CI=true semantic-release |
@jaklan It is most probable, that the $5 is different from what is expected.
Is the fifth argument to the wrapper call with [ "git", "--dry-run", "--no-verify", ... ] the same as the result of running git symbolic-ref -q --short HEAD
in your repository? (The strace command above outputs the info required).
Just as a follow-up - we have eventually decided to overwrite node_modules/semantic-release/lib/git.js
directly instead. We needed to change 2 functions:
- always return
true
inisBranchUpToDate()
:export async function isBranchUpToDate(repositoryUrl, branch, execaOptions) { return true; }
refs/heads/<placeholder>
instead ofbranch
inverifyAuth()
(maybe it could just be replaced with anothergit
function in the dry-run mode, but haven't tested):export async function verifyAuth(repositoryUrl, branch, execaOptions) { try { await execa( "git", ["push", "--dry-run", "--no-verify", repositoryUrl, `HEAD:refs/heads/placeholder`], execaOptions ); } catch (error) { debug(error); throw error; } }
The above could be also reflected in a git
script more or less this way:
#!/usr/bin/env bash
set -eu
git_bin="/usr/bin/git"
if ! [ -x "$git_bin" ]; then
echo >&2 "ERROR: '$git_bin' is not executable"
exit 127
fi
if [ "${1:-}" = "ls-remote" ] &&
[ "${2:-}" = "--heads" ] &&
[ -n "${3:-}" ] &&
[ -n "${4:-}" ]; then
exec $git_bin show-ref --heads "${4}"
elif [ "${1:-}" = "push" ] &&
[ "${2:-}" = "--dry-run" ] &&
[ "${3:-}" = "--no-verify" ] &&
[ -n "${4:-}" ]; then
exec $git_bin "${@:1:4}" "HEAD:refs/heads/placeholder"
else
exec $git_bin "${@}"
fi
Because we changed the approach - I haven't really tested that, but maybe could be helpful for others.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@c0m1c5an5 I had to change it to:
but now works, thanks! I will test it further in CI now (and verify what was the issue with $4 and / or $5)