返回 DeepSeek-Reasonix
resolve-desktop-candidate.sh
根目录 / scripts / resolve-desktop-candidate.sh
1 #!/usr/bin/env bash
2 # Resolve and authorize the immutable source commit for a Desktop publication.
3 # The workflow control plane must run from protected main-v2. Stable/RC builds
4 # use an existing tag on main-v2 history; Preview builds use the exact main-v2
5 # commit selected when the protected workflow was dispatched.
6 set -euo pipefail
7
8 channel="${RELEASE_CHANNEL:?RELEASE_CHANNEL is required}"
9 tag="${RELEASE_TAG:?RELEASE_TAG is required}"
10 orchestrated="${IN_ORCHESTRATED:-false}"
11 orchestrator="${IN_ORCHESTRATOR:-}"
12 approved_sha="${APPROVED_SHA:-}"
13 caller_event="${CALLER_EVENT_NAME:-}"
14 caller_ref="${CALLER_REF:-}"
15 caller_ref_protected="${CALLER_REF_PROTECTED:-}"
16 caller_sha="${CALLER_SHA:-}"
17 caller_workflow_sha="${CALLER_WORKFLOW_SHA:-}"
18 release_remote="${RELEASE_REMOTE:-origin}"
19 require_current_main="${REQUIRE_CURRENT_MAIN:-true}"
20 verify_checkout="${VERIFY_RELEASE_CHECKOUT:-false}"
21
22 case "$orchestrated" in
23 true | false) ;;
24 *)
25 echo "::error::IN_ORCHESTRATED must be true or false, got: $orchestrated" >&2
26 exit 2
27 ;;
28 esac
29 if [ "$orchestrated" = "true" ]; then
30 case "$orchestrator" in
31 stable | preview) ;;
32 *)
33 echo "::error::IN_ORCHESTRATOR must be stable or preview for an orchestrated Desktop release, got: $orchestrator" >&2
34 exit 2
35 ;;
36 esac
37 if [ "$orchestrator" != "$channel" ]; then
38 echo "::error::the $orchestrator orchestrator cannot authorize a Desktop $channel candidate" >&2
39 exit 1
40 fi
41 fi
42 case "$require_current_main" in
43 true | false) ;;
44 *)
45 echo "::error::REQUIRE_CURRENT_MAIN must be true or false, got: $require_current_main" >&2
46 exit 2
47 ;;
48 esac
49 case "$verify_checkout" in
50 true | false) ;;
51 *)
52 echo "::error::VERIFY_RELEASE_CHECKOUT must be true or false, got: $verify_checkout" >&2
53 exit 2
54 ;;
55 esac
56
57 stable_tag_pattern='^desktop-v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-([0-9A-Za-z-]+)(\.[0-9A-Za-z-]+)*)?)?$'
58 preview_tag_pattern='^desktop-v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)-preview\.(0|[1-9][0-9]*)$'
59
60 case "$channel" in
61 stable)
62 if [[ ! "$tag" =~ $stable_tag_pattern ]] || [[ "$tag" =~ $preview_tag_pattern ]]; then
63 echo "::error::Stable Desktop candidate requires desktop-vMAJOR.MINOR.PATCH[-PRERELEASE], excluding -preview.N: $tag" >&2
64 exit 1
65 fi
66 ;;
67 preview)
68 if [[ ! "$tag" =~ $preview_tag_pattern ]]; then
69 echo "::error::Preview Desktop candidate requires desktop-vMAJOR.MINOR.PATCH-preview.N: $tag" >&2
70 exit 1
71 fi
72 ;;
73 *)
74 echo "::error::Desktop release channel must be stable or preview, got: $channel" >&2
75 exit 2
76 ;;
77 esac
78
79 git fetch "$release_remote" main-v2 --tags
80 main_sha="$(git rev-parse "$release_remote/main-v2^{commit}")"
81
82 if [ "$orchestrated" = "true" ]; then
83 candidate="$approved_sha"
84 else
85 if [ "$caller_event" != "workflow_dispatch" ] ||
86 [ "$caller_ref" != "refs/heads/main-v2" ] ||
87 [ "$caller_ref_protected" != "true" ]; then
88 echo "::error::standalone Desktop releases must run from protected main-v2" >&2
89 exit 1
90 fi
91 if [ "$caller_sha" != "$caller_workflow_sha" ]; then
92 echo "::error::standalone Desktop workflow SHA is $caller_workflow_sha, expected caller SHA $caller_sha" >&2
93 exit 1
94 fi
95 if [ "$channel" = "preview" ]; then
96 candidate="$caller_sha"
97 else
98 candidate="$(git rev-parse "$tag^{commit}")"
99 fi
100 fi
101
102 if [[ ! "$candidate" =~ ^[0-9a-f]{40}$ ]]; then
103 echo "::error::Desktop candidate SHA must be a full commit SHA, got: $candidate" >&2
104 exit 1
105 fi
106 if ! git cat-file -e "$candidate^{commit}" 2>/dev/null; then
107 echo "::error::Desktop candidate commit is unavailable: $candidate" >&2
108 exit 1
109 fi
110 if ! git merge-base --is-ancestor "$candidate" "$main_sha"; then
111 echo "::error::Desktop candidate $candidate is not on main-v2 history at $main_sha" >&2
112 exit 1
113 fi
114
115 if [ "$channel" = "stable" ]; then
116 tag_sha="$(git rev-parse "$tag^{commit}")"
117 if [ "$tag_sha" != "$candidate" ]; then
118 echo "::error::$tag points to $tag_sha, expected Desktop candidate $candidate" >&2
119 exit 1
120 fi
121 elif git show-ref --verify --quiet "refs/tags/$tag"; then
122 echo "::error::Desktop Preview uses an immutable asset directory, not a Git tag: $tag" >&2
123 exit 1
124 elif [ "$orchestrated" != "true" ] && [ "$require_current_main" = "true" ] && [ "$candidate" != "$main_sha" ]; then
125 echo "::error::Desktop Preview must use current main-v2 $main_sha, got: $candidate" >&2
126 exit 1
127 fi
128
129 if [ "$verify_checkout" = "true" ]; then
130 head_sha="$(git rev-parse HEAD^{commit})"
131 if [ "$head_sha" != "$candidate" ]; then
132 echo "::error::Desktop release checkout is $head_sha, expected candidate $candidate" >&2
133 exit 1
134 fi
135 fi
136
137 echo "sha=$candidate" >>"${GITHUB_OUTPUT:-/dev/stdout}"
138 echo "Desktop candidate verified: channel=$channel tag=$tag sha=$candidate"
139
139 lines BASH