build: add immutable aws preview sync

This commit is contained in:
Logic
2026-08-26 12:20:38 +08:00
parent fcdcfe2428
commit b84cb3a73a
4 changed files with 289 additions and 0 deletions
+94
View File
@@ -0,0 +1,94 @@
#!/usr/bin/env bash
set -euo pipefail
preview_region=${AWS_REGION:-us-east-1}
preview_profile=${AWS_PROFILE:-hertzbeat-agent}
preview_repository=${PREVIEW_REPOSITORY:-hertzbeat-preview}
preview_branch=${PREVIEW_BRANCH:-preview/zhaoqingran/main}
preview_remote="https://git-codecommit.${preview_region}.amazonaws.com/v1/repos/${preview_repository}"
preview_root=$(git rev-parse --show-toplevel)
preview_temp_dir=$(mktemp -d "${TMPDIR:-/tmp}/hertzbeat-preview.XXXXXX")
preview_index="${preview_temp_dir}/index"
cleanup_preview_temp_dir() {
if [[ -n ${preview_temp_dir:-} && -d ${preview_temp_dir} && ${preview_temp_dir} == *hertzbeat-preview.* ]]; then
rm -rf -- "${preview_temp_dir}"
fi
}
trap cleanup_preview_temp_dir EXIT
cd "${preview_root}"
preview_status_before=$(git status --porcelain=v1 -z | git hash-object --stdin)
GIT_INDEX_FILE="${preview_index}" git read-tree HEAD
GIT_INDEX_FILE="${preview_index}" git add -u
while IFS= read -r -d '' preview_untracked_path; do
GIT_INDEX_FILE="${preview_index}" git add -- "${preview_untracked_path}"
done < <(
git ls-files --others --exclude-standard -z -- \
web-app/src \
script/dev-preview \
':(glob)hertzbeat-*/**/src/**'
)
preview_sequence=$(date -u +%Y%m%dT%H%M%SZ)
preview_metadata=$(printf 'preview-sequence=%s\ncanonical-head=%s\n' "${preview_sequence}" "$(git rev-parse HEAD)")
preview_metadata_blob=$(printf '%s' "${preview_metadata}" | git hash-object -w --stdin)
GIT_INDEX_FILE="${preview_index}" git update-index \
--add \
--cacheinfo "100644,${preview_metadata_blob},.hertzbeat-preview-revision"
preview_tree=$(GIT_INDEX_FILE="${preview_index}" git write-tree)
preview_aws_args=(--region "${preview_region}")
preview_git_args=(-c credential.helper=)
if [[ -n ${preview_profile} ]]; then
preview_aws_args+=(--profile "${preview_profile}")
preview_git_args+=(
-c "credential.helper=!aws --profile ${preview_profile} codecommit credential-helper \$@"
)
else
preview_git_args+=(-c 'credential.helper=!aws codecommit credential-helper $@')
fi
preview_git_args+=(-c credential.UseHttpPath=true)
preview_parent=$(
aws codecommit get-branch \
"${preview_aws_args[@]}" \
--repository-name "${preview_repository}" \
--branch-name "${preview_branch}" \
--query branch.commitId \
--output text 2>/dev/null || true
)
preview_commit_args=("${preview_tree}")
if [[ ${preview_parent} =~ ^[0-9a-f]{40}$ ]]; then
git "${preview_git_args[@]}" fetch --quiet --no-tags "${preview_remote}" "refs/heads/${preview_branch}"
preview_parent=$(git rev-parse FETCH_HEAD)
preview_commit_args+=(-p "${preview_parent}")
fi
preview_commit=$(
printf 'HertzBeat preview %s\n' "${preview_sequence}" |
GIT_AUTHOR_NAME='HertzBeat Preview' \
GIT_AUTHOR_EMAIL='preview@localhost' \
GIT_COMMITTER_NAME='HertzBeat Preview' \
GIT_COMMITTER_EMAIL='preview@localhost' \
git commit-tree "${preview_commit_args[@]}"
)
git "${preview_git_args[@]}" push --quiet "${preview_remote}" \
"+${preview_commit}:refs/heads/${preview_branch}"
preview_status_after=$(git status --porcelain=v1 -z | git hash-object --stdin)
if [[ ${preview_status_before} != "${preview_status_after}" ]]; then
echo 'Preview snapshot unexpectedly changed the local worktree or index.' >&2
exit 1
fi
printf '{"branch":"%s","commit":"%s","tree":"%s","sequence":"%s"}\n' \
"${preview_branch}" \
"${preview_commit}" \
"${preview_tree}" \
"${preview_sequence}"
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -euo pipefail
preview_previous=${1:-}
preview_desired=${2:?desired preview commit is required}
preview_source_dir=${PREVIEW_SOURCE_DIR:-/opt/hertzbeat-preview/source}
if [[ ${preview_previous} =~ ^[0-9a-f]{40}$ ]] &&
git -C "${preview_source_dir}" cat-file -e "${preview_previous}^{commit}" 2>/dev/null; then
if git -C "${preview_source_dir}" diff --quiet "${preview_previous}" "${preview_desired}" -- \
web-app/package.json web-app/pnpm-lock.yaml web-app/pnpm-workspace.yaml; then
:
else
pnpm --dir "${preview_source_dir}/web-app" install --frozen-lockfile
fi
fi
"${preview_source_dir}/script/dev-preview/remote-backend-reload.sh" \
"${preview_previous}" "${preview_desired}"
+112
View File
@@ -0,0 +1,112 @@
#!/usr/bin/env bash
set -euo pipefail
preview_previous=${1:-}
preview_desired=${2:?desired preview commit is required}
preview_source_dir=${PREVIEW_SOURCE_DIR:-/opt/hertzbeat-preview/source}
preview_state_dir=${PREVIEW_STATE_DIR:-/opt/hertzbeat-preview/state}
preview_backend_service=${PREVIEW_BACKEND_SERVICE:-hertzbeat-preview-backend.service}
preview_dry_run=${PREVIEW_BACKEND_DRY_RUN:-false}
install -d -m 0755 "${preview_state_dir}"
preview_full_reactor=false
preview_backend_changed=false
declare -A preview_module_set=()
if [[ ! ${preview_previous} =~ ^[0-9a-f]{40}$ ]] ||
! git -C "${preview_source_dir}" cat-file -e "${preview_previous}^{commit}" 2>/dev/null; then
preview_full_reactor=true
preview_backend_changed=true
else
while IFS= read -r preview_path; do
case "${preview_path}" in
pom.xml|mvnw|mvnw.cmd|.mvn/*)
preview_full_reactor=true
preview_backend_changed=true
;;
*/pom.xml)
preview_full_reactor=true
preview_backend_changed=true
;;
hertzbeat-*/src/*|hertzbeat-*-*/src/*)
preview_backend_changed=true
preview_candidate=$(dirname "${preview_path}")
while [[ ${preview_candidate} != . && ${preview_candidate} != / ]]; do
if [[ -f ${preview_source_dir}/${preview_candidate}/pom.xml ]]; then
preview_module_set["${preview_candidate}"]=1
break
fi
preview_candidate=$(dirname "${preview_candidate}")
done
;;
esac
done < <(git -C "${preview_source_dir}" diff --name-only "${preview_previous}" "${preview_desired}")
fi
if [[ ${preview_backend_changed} != true ]]; then
if [[ ${preview_dry_run} == true ]]; then
printf 'backend=none\n'
fi
exit 0
fi
if [[ ${preview_dry_run} == true ]]; then
if [[ ${preview_full_reactor} == true ]]; then
printf 'backend=full\n'
else
printf 'backend=modules:'
printf '%s\n' "${!preview_module_set[@]}" | LC_ALL=C sort | paste -sd, -
fi
exit 0
fi
printf '%s\n' "${preview_desired}" >"${preview_state_dir}/backend-applying"
preview_maven_args=(
-T 1C
-DskipTests
-DskipITs
-Dsurefire.failIfNoSpecifiedTests=false
-DfailIfNoTests=false
)
if [[ ${preview_full_reactor} == true ]]; then
preview_maven_args+=(-pl hertzbeat-startup -am install)
else
preview_modules=$(
printf '%s\n' "${!preview_module_set[@]}" |
LC_ALL=C sort |
paste -sd, -
)
if [[ -z ${preview_modules} ]]; then
echo 'Backend changes were detected without a resolvable Maven module.' >&2
exit 1
fi
preview_maven_args+=(-pl "${preview_modules}" -am install)
fi
preview_started_at=$(date +%s)
(
cd "${preview_source_dir}"
./mvnw "${preview_maven_args[@]}"
)
systemctl restart "${preview_backend_service}"
for _ in $(seq 1 120); do
if curl --fail --silent --show-error \
http://127.0.0.1:1157/api/setup/status >/dev/null 2>&1; then
preview_finished_at=$(date +%s)
printf '%s\n' "${preview_desired}" >"${preview_state_dir}/backend-active"
printf '%s\n' "$((preview_finished_at - preview_started_at))" \
>"${preview_state_dir}/backend-last-seconds"
rm -f "${preview_state_dir}/backend-applying" "${preview_state_dir}/backend-failed"
exit 0
fi
sleep 2
done
printf '%s\n' "${preview_desired}" >"${preview_state_dir}/backend-failed"
echo 'Backend did not become ready after the controlled restart.' >&2
exit 1
+63
View File
@@ -0,0 +1,63 @@
#!/usr/bin/env bash
set -euo pipefail
preview_region=${AWS_REGION:-us-east-1}
preview_repository=${PREVIEW_REPOSITORY:-hertzbeat-preview}
preview_branch=${PREVIEW_BRANCH:-preview/zhaoqingran/main}
preview_source_dir=${PREVIEW_SOURCE_DIR:-/opt/hertzbeat-preview/source}
preview_state_dir=${PREVIEW_STATE_DIR:-/opt/hertzbeat-preview/state}
preview_remote="https://git-codecommit.${preview_region}.amazonaws.com/v1/repos/${preview_repository}"
preview_git_args=(
-c credential.helper=
-c "credential.helper=!aws --region ${preview_region} codecommit credential-helper \$@"
-c credential.UseHttpPath=true
)
install -d -m 0755 "${preview_state_dir}"
exec 9>"${preview_state_dir}/sync.lock"
flock -n 9 || exit 0
preview_desired=$(
aws codecommit get-branch \
--region "${preview_region}" \
--repository-name "${preview_repository}" \
--branch-name "${preview_branch}" \
--query branch.commitId \
--output text
)
if [[ ! ${preview_desired} =~ ^[0-9a-f]{40}$ ]]; then
echo "Invalid desired preview commit: ${preview_desired}" >&2
exit 1
fi
preview_active=''
if [[ -f ${preview_state_dir}/active ]]; then
preview_active=$(<"${preview_state_dir}/active")
fi
if [[ ${preview_active} == "${preview_desired}" ]]; then
exit 0
fi
printf '%s\n' "${preview_desired}" >"${preview_state_dir}/desired"
printf '%s\n' "${preview_desired}" >"${preview_state_dir}/applying"
git -C "${preview_source_dir}" "${preview_git_args[@]}" fetch --quiet --no-tags "${preview_remote}" \
"refs/heads/${preview_branch}"
preview_fetched=$(git -C "${preview_source_dir}" rev-parse FETCH_HEAD)
if [[ ${preview_fetched} != "${preview_desired}" ]]; then
echo "Preview head advanced during fetch; reconciliation will retry." >&2
exit 75
fi
git -C "${preview_source_dir}" reset --hard "${preview_desired}" >/dev/null
if [[ -x ${preview_state_dir}/after-sync ]]; then
"${preview_state_dir}/after-sync" "${preview_active}" "${preview_desired}"
fi
printf '%s\n' "${preview_desired}" >"${preview_state_dir}/active"
date -u +%Y-%m-%dT%H:%M:%SZ >"${preview_state_dir}/updated-at"
rm -f "${preview_state_dir}/applying"
printf 'active=%s\n' "${preview_desired}"