#!/bin/bash

## Copyright (C) 2026 - 2026 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.

## AI-Assisted

## Sign+tag HEAD for the parent repo and every submodule.
##
## Preconditions (produced by help-steps/signing-key-create, which
## runs from build-steps.d/1200_prepare-build-machine for real
## builds and ci/dry-run.d/150_signing-key-create for CI dry-run):
##   - signing key for ${DEBEMAIL} in the sq keystore
##   - a maintainer-authorized policy file at one of the
##     ${dist_build_config_dirs_list} entries

set -o errexit
set -o nounset
set -o pipefail
set -o errtrace
shopt -s inherit_errexit
shopt -s shift_verbose

repo_root="$(cd -- "$(dirname -- "$(readlink -f -- "${BASH_SOURCE[0]}")")/.." && pwd)"

export dist_build_source_run=true
export dist_build_one_parsed=true
# shellcheck source=help-steps/pre
source "${repo_root}/help-steps/pre"
# shellcheck source=help-steps/variables
source "${repo_root}/help-steps/variables"

cd -- "${repo_root}"

## Opt-out for local work via dist_build_sign_and_tag (set in
## help-steps/variables; default 'true', overridden via --sign-and-tag or a
## buildconfig.d snippet).
if [ ! "${dist_build_sign_and_tag}" = "true" ]; then
   true "INFO: ${BASH_SOURCE[0]}: dist_build_sign_and_tag=${dist_build_sign_and_tag}, skipping sign+tag."
   exit 0
fi

## Redistributable builds rely on offline-signed upstream tags;
## re-tagging or re-signing locally defeats the offline-key trust
## root. CI is exempt - the dry-run pipeline runs against a
## CI-generated signing key and still needs to exercise sign-and-tag.
if [ "${dist_build_redistributable}" = 'true' ]; then
   true "INFO: ${BASH_SOURCE[0]}: dist_build_redistributable=true detected"
   if [ "${CI}" = 'true' ]; then
      true "INFO: ${BASH_SOURCE[0]}: CI=true, allowing sign+tag"
   else
      printf '%s\n' \
         "${BASH_SOURCE[0]}: refusing to run for redistributable build" \
         "  (dist_build_redistributable=true, CI is not 'true')" \
         "Redistributable builds use offline-signed upstream tags" \
         "exclusively." >&2
      exit 1
   fi
fi

if [ -z "${openpgp_policy_file_resolved}" ]; then
   printf '%s\n' \
      "${BASH_SOURCE[0]}: no ${openpgp_policy_filename} found in any of:" \
      "${openpgp_policy_search_paths[@]}" \
      "Run help-steps/signing-key-create or pre-provision a path manually." >&2
   exit 1
fi
printf '%s\n' "${BASH_SOURCE[0]}: using policy ${sq_git_policy_file}"

## Fail fast on a misconfigured keystore (e.g. split-gpg-2
## unreachable) before sign-tag-head's destructive 'commit --amend -S'
## walks every submodule.
./help-steps/signing-key-test

## Phase 1: sign submodules first (recursively, depth-first per
## git's foreach order). For submodules whose HEAD is unsigned,
## sign-tag-head runs 'commit --amend -S' which changes the
## submodule's HEAD SHA. For submodules already at a signed-tag
## release, sign-tag-head is a no-op for that submodule's HEAD.
##
## $toplevel + $displaypath are set by foreach in the child shell;
## passed as context label so per-submodule output identifies its
## origin.
# shellcheck disable=SC2016
git submodule foreach --recursive '"$toplevel/help-steps/sign-tag-head" "$displaypath"'

## Phase 2: stage updated gitlinks in the parent's index so the
## parent's about-to-happen amend in Phase 3 captures the
## post-Phase-1 submodule HEADs. Iterate top-level submodules only
## (no --recursive) - 'git add -- <path>' from the outermost repo
## against a path inside another submodule fails ('submodule X is
## contained in path'); intermediate submodules update their own
## gitlinks via THEIR amend during Phase 1.
# shellcheck disable=SC2016
git submodule foreach '
   cd "$toplevel"
   git add -- "$displaypath"
'

## Phase 3: sign the parent. The amend now includes the staged
## submodule gitlink updates from Phase 2.
./help-steps/sign-tag-head 'main repo'
