Prepare production artifacts before release
This commit is contained in:
parent
d79e4e436b
commit
9aa371105f
|
|
@ -1272,6 +1272,21 @@ allows only the absent Play App Signing certificate; the stricter
|
|||
publishing Android through Google Play. The plan neither uploads a bundle nor
|
||||
creates a backup.
|
||||
|
||||
Prepare and verify the immutable Git bundle and `linux/amd64` image archive on
|
||||
the development workstation before authorising any production mutation:
|
||||
|
||||
```bash
|
||||
./scripts/production-release-clean.sh prepare whoneedhelp
|
||||
```
|
||||
|
||||
`prepare` repeats the read-only production and environment checks, reads the
|
||||
production image-build inputs into a mode-`0600` temporary file, and then
|
||||
creates or verifies the commit-bound artifacts under `output/releases/`. It
|
||||
does not upload an artifact, create a production backup, change the remote
|
||||
checkout, load an image, run a migration, or restart a service. A later
|
||||
`apply` for the same commit verifies and reuses those exact artifacts instead
|
||||
of compiling them again.
|
||||
|
||||
After reviewing the exact commit printed by the plan, execution additionally
|
||||
requires an explicit per-commit confirmation:
|
||||
|
||||
|
|
@ -1361,6 +1376,8 @@ including those edits:
|
|||
```bash
|
||||
./scripts/production-release-clean.sh plan whoneedhelp
|
||||
|
||||
./scripts/production-release-clean.sh prepare whoneedhelp
|
||||
|
||||
WNH_PRODUCTION_RELEASE_CONFIRM='whoneedhelp.com:EXACT_COMMIT' \
|
||||
./scripts/production-release-clean.sh apply whoneedhelp
|
||||
```
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ action=${1:-plan}
|
|||
ssh_target=${2:-whoneedhelp}
|
||||
|
||||
case "$action" in
|
||||
plan | apply) ;;
|
||||
plan | prepare | apply) ;;
|
||||
*)
|
||||
echo "Usage: $0 [plan|apply] [SSH_TARGET]" >&2
|
||||
echo "Usage: $0 [plan|prepare|apply] [SSH_TARGET]" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ remote_root=${WNH_PRODUCTION_REMOTE_ROOT:-/srv/who_need_help-production}
|
|||
expected_domain=${WNH_PRODUCTION_DOMAIN:-whoneedhelp.com}
|
||||
|
||||
case "$action" in
|
||||
plan | apply) ;;
|
||||
plan | prepare | apply) ;;
|
||||
*)
|
||||
echo "Usage: $0 [plan|apply] [SSH_TARGET]" >&2
|
||||
echo "Usage: $0 [plan|prepare|apply] [SSH_TARGET]" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
|
@ -106,13 +106,14 @@ if [[ -n "$(git -C "$ROOT" status --porcelain --untracked-files=no)" ]]; then
|
|||
fi
|
||||
|
||||
confirmation="$expected_domain:$local_commit"
|
||||
if [[ "${WNH_PRODUCTION_RELEASE_CONFIRM:-}" != "$confirmation" ]]; then
|
||||
if [[ "$action" == "apply" ]]; then
|
||||
if [[ "${WNH_PRODUCTION_RELEASE_CONFIRM:-}" != "$confirmation" ]]; then
|
||||
echo "Release execution requires explicit approval in this exact process:" >&2
|
||||
echo "WNH_PRODUCTION_RELEASE_CONFIRM=$confirmation $0 apply $ssh_target" >&2
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$migration_policy" == "forward_only" ]]; then
|
||||
if [[ "$migration_policy" == "forward_only" ]]; then
|
||||
forward_confirmation="$expected_domain:$local_commit:forward-only"
|
||||
if [[ "${WNH_PRODUCTION_FORWARD_ONLY_CONFIRM:-}" != "$forward_confirmation" ]]; then
|
||||
echo "This release contains migrations that are not safe for an automatic old-image rollback." >&2
|
||||
|
|
@ -122,6 +123,7 @@ if [[ "$migration_policy" == "forward_only" ]]; then
|
|||
echo " WNH_PRODUCTION_RELEASE_CONFIRM=$confirmation $0 apply $ssh_target" >&2
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
"$ROOT/scripts/prepare-production-release.sh"
|
||||
|
|
@ -151,6 +153,11 @@ chmod 600 "$production_env"
|
|||
"$ROOT/scripts/prepare-production-images.sh" "$production_env"
|
||||
cleanup_production_env
|
||||
|
||||
if [[ "$action" == "prepare" ]]; then
|
||||
echo "Production release artifacts are prepared and verified locally; no remote state was changed."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
remote_release_dir="$remote_root/output/releases/incoming"
|
||||
remote_bundle="$remote_release_dir/$(basename -- "$bundle")"
|
||||
remote_image_archive="$remote_release_dir/$(basename -- "$image_archive")"
|
||||
|
|
|
|||
|
|
@ -119,6 +119,22 @@ class ProductionReleaseCleanTest(unittest.TestCase):
|
|||
self.assertEqual(result.returncode, 23)
|
||||
self.assert_release_worktree_removed()
|
||||
|
||||
def test_prepare_is_forwarded_through_the_same_clean_checkout(self):
|
||||
dirty = self.project / "README.md"
|
||||
dirty.write_text("user-owned change\n", encoding="utf-8")
|
||||
|
||||
self.run_command(
|
||||
[str(self.scripts / WRAPPER.name), "prepare", "production-alias"],
|
||||
env=self.environment(),
|
||||
)
|
||||
|
||||
captured = self.capture.read_text(encoding="utf-8")
|
||||
self.assertIn("status=\n", captured)
|
||||
self.assertIn("args=prepare production-alias", captured)
|
||||
self.assertIn(f"commit={self.commit}", captured)
|
||||
self.assertEqual(dirty.read_text(encoding="utf-8"), "user-owned change\n")
|
||||
self.assert_release_worktree_removed()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user