From e2d1ec14a4be835be2c01d2550b6542f5c82b832 Mon Sep 17 00:00:00 2001 From: Magnus Andersson Date: Tue, 26 Mar 2024 14:03:38 +0100 Subject: [PATCH] Change implementaion of bump-tag --- bump-tag | 328 ++++++++++++------------------------------------------- 1 file changed, 67 insertions(+), 261 deletions(-) diff --git a/bump-tag b/bump-tag index 9352245..ee89988 100755 --- a/bump-tag +++ b/bump-tag @@ -1,275 +1,81 @@ #!/bin/bash +set -e -echo "Fetching updates from $(git remote get-url origin) ..." +echo "Fetching any updates from server:" +git pull echo "" -if ! git pull --verify-signatures; then - echo "WARNING: git pull did not exit successfully." - echo "" - echo "EXITING the script. In order to tag your changes," - echo "investigate and then run bump-tag again." - exit 1 -fi -if [[ -f ./cosmos.conf ]]; then - # shellcheck disable=SC1091 - source ./cosmos.conf -fi +cur_branch=$(git branch --show-current) -# A tab will be used in multiple commands for git -t=$'\t' - -# Set the default tag according to the repo -# or by entering a name as the first argument. -if [[ -z "${1}" ]]; then - deftag="$(basename "${PWD}")" +if [[ -z ${1} ]]; then + deftag="${cur_branch}" else - deftag="${1}" + deftag="${1}" fi -# Set the tag prefix according to: -# 1. $tag, if specified in cosmos.conf, -# 2. or $deftag, as specified above. -# shellcheck disable=SC2154 -if [[ -n "${tag}" ]]; then - tagpfx="${tag}" +if ! [[ ${deftag} =~ ${cur_branch} ]] && ! [[ ${GIT_PUSH_EXTRA} =~ '--no-verify' ]]; then + echo "Your tag: ${deftag} does not match the name of the branch: ${cur_branch}." + echo "To push anyway, run: GIT_PUSH_EXTRA='--no-verify' ${0} ${*}" + exit 1 +fi + +tagpfx=${tag:="${deftag}"} + +if [[ -z ${ALLOW_NEW_TAG} ]]; then + echo "${0}: Looking for last-tag matching ${tagpfx}-2*" + last_tag=$(git tag -l "${tagpfx}-2*" | sort | tail -1) + + if [[ -z ${last_tag} ]]; then + echo "" + echo -e "Tag matching \e[1m${tagpfx}-2* NOT FOUND\e[0m, aborting." + echo "To create new tag, run: ALLOW_NEW_TAG=true ${0} ${*}" + exit 1 + fi + + echo -e "Verifying last tag \e[94m${last_tag}\e[0m:" + (git tag -v "${last_tag}" 2>&1 | grep ^gpg:) || true + # again to not mask exit status of git with grep + git tag -v "${last_tag}" >/dev/null 2>&1 + echo "" + echo "Differences between tag ${last_tag} and what you are about to sign:" + git log --pretty=format:'%h %an %G? %s' --graph "${last_tag}..HEAD" + + echo "Press enter to see diff" + read -r + + PAGER="cat" git diff --color "${last_tag}"..HEAD + iter=1 + ok= + + while test -z "${ok}"; do + this_tag=$(date "+${tagpfx}-%Y-%m-%d-v$(printf "%02d" ${iter})") + iter=$((iter + 1)) + case $( ( + echo "${this_tag}" + echo "${last_tag}" + ) | sort | tail -1) in + "${last_tag}") ;; + "${this_tag}") + ok=yes + ;; + esac + done + extra_message=" AND DIFF ABOVE" else - tagpfx="${deftag}" + this_tag=$(date "+${tagpfx}-%Y-%m-%d-v1") fi -# This is the current branch that Git will diff against. -this_branch=$(git rev-parse --abbrev-ref HEAD) +echo "" +echo -e "Using new tag \e[94m${this_tag}\e[0m" +echo -e "\e[1mONLY SIGN IF YOU APPROVE OF VERIFICATION${extra_message}\e[0m" -# Check why the tag couldn't be verified -# First argument: the tag to investigate -check_tag_sig_failure() -{ - local __tag_to_check="${1}" - - # shellcheck disable=SC2155 - local __verify_tag_output="$(git verify-tag --raw "${__tag_to_check}" 2>&1)" - - if echo "${__verify_tag_output}" | grep -q "VALIDSIG"; then - - if echo "${__verify_tag_output}" | grep -q "EXPKEYSIG"; then - - echo "" - echo "WARNING: The tag was correctly signed, but the copy of" - echo "the key that you have stored on your computer has expired." - echo "Check for an updated key in:" - echo "global/overlay/etc/cosmos/keys/" - echo "" - echo "EXITING the script. In order to tag your changes," - echo "investigate and then run bump-tag again." - exit 1 - - else - - echo "" - echo "WARNING: The tag was probably correctly signed," - echo "but it still didn't pass the verification check." - echo "" - echo "EXITING the script. In order to tag your changes," - echo "investigate and then run bump-tag again." - exit 1 - - fi - - else - - echo "" - echo "WARNING: The signature of the tag could not be verified." - echo "Please make sure that you have imported the key and that" - echo "the key is signed by a trusted party." - echo "Keys used for signing in a Cosmos repo can be found at:" - echo "global/overlay/etc/cosmos/keys/" - echo "" - echo "EXITING the script. In order to tag your changes," - echo "investigate and then run bump-tag again." - exit 1 - - fi -} - -check_commit_sig_failure() -{ - local __commit_to_check="${1}" - local __file_related_to_commit="${2}" - - # shellcheck disable=SC2155 - local __verify_commit_output="$(git verify-commit --raw "${__commit_to_check}" 2>&1)" - - if echo "${__verify_commit_output}" | grep -q "VALIDSIG"; then - - if echo "${__verify_commit_output}" | grep -q "EXPKEYSIG"; then - - echo "WARNING: The commit to ${__file_related_to_commit}" - echo "was correctly signed, but the copy of the key that" - echo "you have stored on your computer has expired." - echo "Check for an updated key in:" - echo "global/overlay/etc/cosmos/keys/" - echo "" - echo "EXITING the script. In order to tag your changes," - echo "investigate and then run bump-tag again." - exit 1 - - else - - echo "WARNING: The commit to ${__file_related_to_commit}" - echo "was probably correctly signed, but it still didn't" - echo "pass the verification check." - echo "" - echo "EXITING the script. In order to tag your changes," - echo "investigate and then run bump-tag again." - exit 1 - - fi - - else - - echo "WARNING: The commit to ${__file_related_to_commit}" - echo "could not be verified. Please make sure that you have" - echo "imported the key and that the key is signed by a trusted party." - echo "" - echo "EXITING the script. In order to tag your changes," - echo "investigate and then run bump-tag again." - exit 1 - - fi -} - -# Verify the last commit of a file -# First argument: the file to verify -verify_last_commit() -{ - local __file_to_verify="${1}" - - if [[ ! -f "${__file_to_verify}" ]]; then - return 1 - fi - - if [[ -n "$(git status --porcelain "${__file_to_verify}")" ]]; then - echo "" - echo "INFO: local changes detected in ${__file_to_verify}," - echo "Not checking the signature of the last commit to ${__file_to_verify}." - echo "" - return 1 - fi - - # shellcheck disable=SC2155 - local __last_commit="$(git log -n 1 --pretty=format:%H -- "${__file_to_verify}")" - - if ! git verify-commit "${__last_commit}" 2> /dev/null; then - echo "" - echo "WARNING: Untrusted modification to ${__file_to_verify}:" - echo "----------------------------" - git verify-commit "$(git log -n 1 --pretty=format:%H -- "${__file_to_verify}")" - echo "----------------------------" - - check_commit_sig_failure "${__last_commit}" "${__file_to_verify}" - fi -} - -tag_list="$(git tag -l "${tagpfx}-*")" -# shellcheck disable=SC2181 -if [[ ${?} -ne 0 ]] || [[ -z "${tag_list}" ]]; then - - if [[ -z ${ALLOW_UNSIGNED_COMMITS_WITHOUT_TAGS} ]]; then - echo "No tags found, verifying all commits instead." - echo "Please set environment variable ALLOW_UNSIGNED_COMMITS_WITHOUT_TAGS if you want to disable this check." - # %H = commit hash - # %G? = show "G" for a good (valid) signature - git_log="$(git log --pretty="format:%H${t}%G?" \ - --first-parent \ - | grep -v "${t}G$")" - fi - -else - - last_tag="$(echo "${tag_list}" | sort | tail -1)" - echo "Verifying last tag: ${last_tag} and the commits after that" - - if ! git verify-tag "${last_tag}"; then - check_tag_sig_failure "${last_tag}" - fi - - tag_object="$(git verify-tag -v "${last_tag}" 2>&1 | grep ^object | cut -d' ' -f2)" - - # The commits after the last valid signed git tag that we need to check - revision_range="${tag_object}..HEAD" - - # Filter out the commits that are unsigned or untrusted - # %H = commit hash - # %G? = show "G" for a good (valid) signature - git_log="$(git log --pretty="format:%H${t}%G?" "${revision_range}" \ - --first-parent \ - | grep -v "${t}G$")" - -fi - -if [[ -n "${git_log}" ]]; then - echo "" - echo -e "------WARNING: unsigned or untrusted commits after the last tag------" - echo "${git_log}" - echo -e "---------------------------------------------------------------------" - echo "Quick referens on how to configure signing of commits in ~/.gitconfig:" - echo "[user]" - echo " signingkey = your-prefered-key-id" - echo "[commit]" - echo " gpgsign = true" - echo "" - echo "EXITING the script. In order to tag your changes," - echo "please make sure that you have configured signing of" - echo "your own commits and that the listed unsigned commits" - echo "have been made by a trusted party and are not malicous." - exit 1 -fi - -# Always check that the last commit of certain -# sensitive files is trusted, without taking into -# account whether the last tag was trusted or not. -verify_last_commit "./scripts/jsonyaml-no-output.py" -verify_last_commit "./bump-tag" - -# Test the syntax of each YAML-file to be tagged. -for file in $(git diff --name-only "${last_tag}..${this_branch}" | grep -E "^.*\.(yaml|yml)$"); do - if [[ -f "${file}" ]]; then - ./scripts/jsonyaml-no-output.py yaml "${file}" - fi -done - -echo "Differences between tag ${last_tag} and what you are about to sign:" -# With PAGER=cat, git diff will simply dump the output to the screen. -# shellcheck disable=SC2037 -PAGER="cat" git diff --color "${last_tag}..${this_branch}" - -# Iterate over the $last_tag until $this_tag is set to a later version -iter=1 -ok= -while [[ -z "${ok}" ]]; do - this_tag="$(date +"${tagpfx}-%Y-%m-%d-v$(printf "%02d" "${iter}")")" - iter="$(( iter + 1))" - - case "$( (echo "${this_tag}"; echo "${last_tag}") | sort | tail -1 )" in - "${last_tag}") - ;; - "${this_tag}") - ok=yes - ;; - esac -done - -if [[ "${deftag}" != "${tagpfx}" ]]; then - echo -e "Using new tag \e[94m${this_tag}\e[0m according to pattern in cosmos.conf" -else - echo -e "Using new tag \e[94m${this_tag}\e[0m" -fi - -echo -e "\e[1mONLY SIGN IF YOU APPROVE OF VERIFICATION AND DIFF ABOVE\e[0m" - -# GITTAGEXTRA is for putting things like "-u 2117364A" -# Note that this variable cannot be quoted if left empty. +# GIT_TAG_EXTRA is for putting things like "-u 2117364A" # shellcheck disable=SC2086 -git tag ${GITTAGEXTRA} -m bump. -s "${this_tag}" +git tag ${GIT_TAG_EXTRA} -m bump. -s "${this_tag}" -git push -git push --tags +# GIT_PUSH_EXTRA is for putting things like "--no-verify" +# shellcheck disable=SC2086 +git push ${GIT_PUSH_EXTRA} + +# shellcheck disable=SC2086 +git push --tags ${GIT_PUSH_EXTRA}