Repository navigation
178 lines (172 loc) Β· 8.17 KB
/
Copy pathpublish.yml
File metadata and controls
178 lines (172 loc) Β· 8.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
name: Publish Package to npmjs
on:
release:
types: [published]
env:
RELEASE_VERSION: ${{ github.event.release.tag_name || github.ref_name }}
permissions:
id-token: write # Required for OIDC
contents: read
statuses: read # native-required gate check
jobs:
check_changes:
runs-on: ubuntu-latest # npm --provenance requires a GitHub-hosted runner
# Room for the native-required wait below.
timeout-minutes: 130
outputs:
harmony_changed: ${{ steps.check.outputs.changed }}
prev_tag: ${{ steps.check.outputs.prev_tag }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
# Only tags, commits and trees are read (git tag --merged, git diff
# --name-only, git rev-parse); skip the blobs of the whole history.
filter: blob:none
# Both publish jobs need this job, so a release can only ship a commit
# whose lint/test/native E2E gate (native-gate.yml posts it as the
# "native-required" commit status) is green. Pending or not yet posted
# (a release cut right after the push) is waited out; failure, error
# or a status that never shows up fails the release.
- name: Require native-required to be green for the release commit
shell: bash
env:
GH_TOKEN: ${{ github.token }}
SHA: ${{ github.sha }}
run: |
# A version-only release commit skips its native jobs on push
# (.github/actions/version-only posts "native-inherited" for it,
# before any of its workflows completes), so its own
# native-required only covers lint and test; the native E2E it
# ships ran on its parent, whose native-required must be green too.
status() {
gh api "repos/$GITHUB_REPOSITORY/commits/$1/status" \
--jq "[.statuses[] | select(.context == \"$2\")][0].state // \"missing\""
}
# The gate turns green only after the slowest native E2E: e2e-ios
# is a build job (timeout 45 min) followed by its test legs
# (timeout 60 min), plus macOS queueing. A green release commit
# took 55 min (10.60.0), so 45 failed releases cut right after the
# push; wait out both budgets instead.
# Checks at minute 0 through 120: the last poll lands on the
# boundary itself, with no trailing sleep before giving up.
required="$SHA"
for attempt in $(seq 0 120); do
green=true
for sha in $required; do
state="$(status "$sha" native-required)"
echo "native-required for $sha: $state"
case "$state" in
success) ;;
pending|missing) green=false ;;
*) echo "::error::native-required is $state for $sha; fix CI before publishing"; exit 1 ;;
esac
done
if [ "$green" = true ]; then
if [ "$required" = "$SHA" ] && [ "$(status "$SHA" native-inherited)" = success ]; then
required="$SHA $(git rev-parse "$SHA^1")"
echo "$SHA only bumps the version; also requiring its parent's native-required."
continue
fi
exit 0
fi
if [ "$attempt" -lt 120 ]; then sleep 60; fi
done
echo "::error::native-required for $required did not turn green within 120 minutes"
exit 1
- name: Check Harmony changes
id: check
shell: bash
run: |
# The baseline has to be the newest ancestor tag that actually made it
# to npm, not merely the newest tag: a tag whose publish run failed
# (v10.52.2 died in prepack) exists in git but not on the registry, and
# "Fetch previous Harmony HAR" pulls that version's tarball from npm.
# Picking it would fail the whole publish on ETARGET.
PREV_TAG=""
for tag in $(git tag --sort=-v:refname --merged HEAD^ | head -20); do
case "$tag" in v[0-9]*) ;; *) continue ;; esac
if npm view "react-native-update@${tag#v}" version >/dev/null 2>&1; then
PREV_TAG="$tag"
break
fi
echo "Skipping $tag: tagged but never published to npm."
done
echo "prev_tag=$PREV_TAG" >> $GITHUB_OUTPUT
if [ -z "$PREV_TAG" ]; then
echo "No previous published tag found, assuming harmony changed."
echo "changed=true" >> $GITHUB_OUTPUT
exit 0
fi
echo "Previous tag is $PREV_TAG"
# The HAR embeds librnpushy.so compiled from cpp/patch_core,
# cpp/update_flow_core, cpp/hpatch and the HDiffPatch/lzma
# submodules (harmony/pushy/src/main/cpp/CMakeLists.txt), so any of
# those changing must rebuild it too β reusing the previous HAR
# would ship Harmony with an older native core than Android/iOS.
if git diff --name-only "$PREV_TAG" HEAD \
| grep -qE '^(harmony|cpp|android/jni)/|^scripts/build-harmony-har\.js$|^\.gitmodules$'; then
echo "harmony HAR inputs changed."
echo "changed=true" >> $GITHUB_OUTPUT
else
echo "harmony HAR inputs have NO changes."
echo "changed=false" >> $GITHUB_OUTPUT
fi
# Rebuild the Android native libraries from source so the published package
# can never ship a stale librnpushy.so after a cpp/patch_core change (the
# committed binaries are for local dev / git installs only).
build_android_so:
runs-on: ubuntu-latest # npm --provenance requires a GitHub-hosted runner
timeout-minutes: 15
env:
# Keep in sync with PINNED_NDK_VERSION in scripts/build-android-so.sh.
NDK_VERSION: 28.2.13676358
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
- name: Install pinned NDK
run: echo "y" | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" "ndk;$NDK_VERSION"
- name: Build and verify native libraries
# The runner image presets ANDROID_NDK_HOME/ANDROID_NDK_ROOT to its
# bundled NDK, which would win over the pinned install in the script's
# resolution order β force the pinned one so published .so files don't
# drift with runner image upgrades.
run: ANDROID_NDK_HOME="$ANDROID_HOME/ndk/$NDK_VERSION" bash scripts/build-android-so.sh
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: android-so
path: android/lib/
if-no-files-found: error
# The two publish jobs differ only in where harmony/pushy.har comes from;
# everything else lives in .github/actions/publish-npm. They stay separate
# jobs: the HAR build needs the HarmonyOS container, the reuse path does not.
publish_with_harmony:
needs: [check_changes, build_android_so]
if: needs.check_changes.outputs.harmony_changed == 'true'
runs-on: ubuntu-latest # npm --provenance requires a GitHub-hosted runner
# Pinned by digest (manifest list of :latest as of 2026-08-30); bump deliberately.
container: ghcr.io/sanchuanhehe/harmony-next-pipeline-docker/harmonyos-ci-image:latest@sha256:2836142b7b6ae8837ad0e36cacc650f00e8c88f55b4e9f34be66cc98a731c5da
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
- name: Build Harmony HAR and publish
uses: ./.github/actions/publish-npm
with:
harmony-har: build
publish_without_harmony:
needs: [check_changes, build_android_so]
if: needs.check_changes.outputs.harmony_changed == 'false'
runs-on: ubuntu-latest # npm --provenance requires a GitHub-hosted runner
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
- name: Reuse the previous Harmony HAR and publish
uses: ./.github/actions/publish-npm
with:
harmony-har: previous
previous-tag: ${{ needs.check_changes.outputs.prev_tag }}