Skip to content

Commit edb4d5b

Browse files
committed
Publish dev versions of the ESP-IDF component from the nightly branch
Projects that need the component before the next release can now pin a dev version from the registry instead of generating the component from an ExecuTorch checkout. A manual run of publish-espressif-idf.yml on the nightly branch with version_suffix -dev publishes X.Y.Z-dev.YYYYMMDD of that branch's commit, through the same packing, testing, review and registry checks as a release. The generator's new --version-suffix -dev stamps HEAD's commit date, and like the other published stamps checks the checkout: HEAD must be on the nightly branch, checked out or fetched from origin, and free of uncommitted changes to what the generator reads. --allow-dev-stamp stays the unchecked stamp for local builds. A dev version's kernel bundles need executorch from the component's exact commit. ExecuTorch's nightly wheels are built from the nightly branch's commits, so the plan refuses -dev on any other ref and any other suffix on the nightly branch. That check runs from the nightly branch's copy of the workflow, which is main's, so it guards against mistakes rather than changes to it: the runbook protects the nightly branch with a ruleset before the environment trusts it, and has the approver of a dev upload review what changed in the workflow and the upload script since the last approved one. Before the build, the new wheel mode of test_espressif_idf_nightly.sh checks that the nightly index has the version's wheels for every platform and CPython the wheel workflows build, and that all of them record that commit, which takes about 30 seconds. It refuses a version dated today, since a second nightly the same day, which has happened, replaces that day's wheels; the runbook has the workflow run between 00:00 UTC and the next nightly, and once with dry_run set before the first dev upload. The nightly matrix gains a job, which its pull requests run, that checks the wheel check's refusals and runs it on the latest finished nightly of the last 60 days that has every wheel; nightly wheels can fail to build for days, so finding none only warns. ExecuTorch's wheels declare no torch, so the component's VERSION now records the torch requirement install_requirements.py builds the wheels against, and the CPU index of its TORCH_URL_BASE, which it installs torch from and which also serves torch release candidates. The generator reads both before --version exits, so the stamp checks catch a pin it cannot read, and counts install_requirements.py among its inputs. The new torch mode checks that the requirement resolves from that index for every platform and CPython, in the package job before upload and in the nightly's prepare job every day, and the component test checks both lines. The component's README gives the exact pip command for its version, and gen_kernels.py names the nightly wheel a dev version needs. The nightly index keeps about 60 days of wheels, so a project moves to a newer dev version, or to the release, before its pin ages out; firmware builds from a committed kernel bundle are unaffected. Dev versions are semver pre-releases, which a version range picks up only if it opts in, so they go to production without reaching projects on releases. They read 1.6.0-dev.YYYYMMDD, as the nightly wheels do, until main's version.txt moves past 1.6.0, and sort below 1.6.0 meanwhile; exact pins are unaffected. Dev runs queue in the nightly branch's concurrency group, so one cannot replace a pending release run. Before the first dev upload, a repo admin protects the nightly branch and adds it to the deployment branches of the esp-component-registry environment. The workflow accepts -dev once this change reaches the nightly branch. Authored with Claude Code.
1 parent 5f1f3ec commit edb4d5b

9 files changed

Lines changed: 342 additions & 53 deletions

File tree

‎.ci/scripts/test_espressif_idf_component.sh‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ bash "${release_clone}/examples/espressif/build_idf_component.sh" --version-suff
9393
--out "${build_dir}/release_component" 2>&1 | tee "${build_dir}/generate-release.log"
9494
compote manifest lint "${build_dir}/release_component"
9595
python - "${build_dir}/release_component" "${release_version}" "$(git rev-parse HEAD)" <<'PY'
96+
import re
9697
import sys
9798
from pathlib import Path
9899
@@ -103,6 +104,13 @@ for line in (f"component_version: {version}", f"executorch_commit: {commit}"):
103104
sys.exit(f"FAIL: the release component's VERSION has no '{line}'")
104105
if not any(l.startswith("generator: ") and l.endswith(" --version-suffix ''") for l in lines):
105106
sys.exit("FAIL: the release component's VERSION does not record --version-suffix ''")
107+
sys.path.insert(0, ".")
108+
from install_requirements import TORCH_URL_BASE
109+
110+
if not any(re.fullmatch(r"torch_requirement: torch==\d+\.\d+\.\d+\S*", l) for l in lines):
111+
sys.exit("FAIL: the release component's VERSION has no torch_requirement: torch==X.Y.Z")
112+
if f"torch_index: {TORCH_URL_BASE}/cpu" not in lines:
113+
sys.exit(f"FAIL: the release component's VERSION has no torch_index: {TORCH_URL_BASE}/cpu")
106114
if f'version: "{version}"' not in (component / "idf_component.yml").read_text().splitlines():
107115
sys.exit(f"FAIL: the release component's idf_component.yml is not version {version}")
108116
print(f"OK: a clean checkout tagged v{version} generates release {version}")

‎.ci/scripts/test_espressif_idf_nightly.sh‎

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,35 @@
3333
# pytorch/executorch, builds the smoke consumer for ESP32-S3 with it, fails
3434
# if the registry serves files other than <dir>'s archive, and runs the
3535
# build on the emulator.
36+
# test_espressif_idf_nightly.sh wheel <dir> <dev version> <commit>
37+
# Checks that the ExecuTorch nightly wheels of the version's date exist for
38+
# every platform and Python and were built from <commit>, so a project can
39+
# install the executorch its kernel bundles need. Refuses today's nightly,
40+
# which a later one could replace. Logs go under <dir>.
41+
# test_espressif_idf_nightly.sh rehearse <dir>
42+
# Checks that wheel refuses a version that is not a dev version and today's
43+
# nightly, then runs it on the latest finished nightly of origin/nightly's
44+
# last 60 days, the nightly index's window, that has every wheel. Nightly
45+
# wheels can fail to build for days, so finding none only warns.
46+
# test_espressif_idf_nightly.sh torch <dir>
47+
# Needs only <dir> from prepare: checks that the torch the component's
48+
# VERSION names resolves from its index for every platform and Python.
3649

3750
set -euo pipefail
3851

3952
et_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
40-
usage="usage: $0 prepare <dir> [stamp options] | build <dir> <shard> <shards> | fetch <dir> <URL> <sha256> | registry <dir> <URL>"
53+
usage="usage: $0 prepare <dir> [stamp options] | build <dir> <shard> <shards> | fetch <dir> <URL> <sha256> | registry <dir> <URL> | wheel <dir> <dev version> <commit> | rehearse <dir> | torch <dir>"
4154
mode=${1:?${usage}}
4255
dir=${2:?${usage}}
4356
mkdir -p "${dir}"
4457
dir=$(cd "${dir}" && pwd)
4558
cd "${et_root}"
4659
targets=(esp32 esp32s3 esp32c3 esp32c5 esp32c6 esp32p4)
60+
# The platforms and CPython versions ExecuTorch's wheels are built for, as
61+
# .github/workflows/build-wheels-{linux,aarch64-linux,macos,windows}.yml set them.
62+
wheel_platforms=(manylinux_2_28_x86_64 manylinux_2_28_aarch64 macosx_14_0_arm64 win_amd64)
63+
wheel_pythons=(311 312 313 314 315)
64+
nightly_index=https://download.pytorch.org/whl/nightly/cpu
4765

4866
# Runs a command with its output in a log, and shows the log's tail if it fails.
4967
logged() {
@@ -395,6 +413,116 @@ settings_applied() {
395413
[[ "${applied}" == true ]]
396414
}
397415

416+
# Prints each wheel a dev version lacks: version, the nightly index's listing.
417+
missing_wheels() {
418+
local listed platform python
419+
listed=$(grep -F "executorch-${1/-dev./.dev}" <<< "$2" || true)
420+
for platform in "${wheel_platforms[@]}"; do
421+
for python in "${wheel_pythons[@]}"; do
422+
grep -qF -- "-cp${python}-cp${python}-${platform}.whl" <<< "${listed}" \
423+
|| echo "cp${python}-${platform}"
424+
done
425+
done
426+
}
427+
428+
# Checks a dev version's nightly wheels: version, commit.
429+
check_wheels() {
430+
local version=$1 commit=$2 listing missing wheels platform python
431+
if [[ "${version}" != *-dev.* ]]; then
432+
echo "FAIL: ${version} is not a dev version" >&2
433+
exit 1
434+
fi
435+
# A second nightly the same day would replace the wheels of this one.
436+
if [[ "${version##*-dev.}" == "$(date -u +%Y%m%d)" ]]; then
437+
echo "FAIL: ${version} is today's nightly, which a later nightly today could replace;" \
438+
"publish it after 00:00 UTC, before the next nightly." >&2
439+
exit 1
440+
fi
441+
# The version's date is its nightly commit's UTC date, and the wheels' is
442+
# the day they were built; when the two differ, no wheels are found.
443+
listing=$(curl -sSf --retry 3 "${nightly_index}/executorch/")
444+
missing=$(missing_wheels "${version}" "${listing}")
445+
if [[ -n "${missing}" ]]; then
446+
echo "FAIL: the nightly index has no ${version} wheel for ${missing//$'\n'/ }" >&2
447+
exit 1
448+
fi
449+
wheels=$(mktemp -d)
450+
# shellcheck disable=SC2064 # wheels is local, so expand it now.
451+
trap "rm -rf '${wheels}'" EXIT
452+
mkdir -p "${dir}/logs"
453+
for platform in "${wheel_platforms[@]}"; do
454+
for python in "${wheel_pythons[@]}"; do
455+
logged "${dir}/logs/nightly-wheel-cp${python}-${platform}.log" python -m pip download \
456+
--no-deps --only-binary=:all: --platform "${platform}" \
457+
--python-version "3.${python#3}" --implementation cp --index-url "${nightly_index}" \
458+
--dest "${wheels}" "executorch==${version/-dev./.dev}"
459+
done
460+
done
461+
python - "${commit}" "${wheels}"/executorch-*.whl <<'PY'
462+
import re
463+
import sys
464+
import zipfile
465+
466+
commit, wheels = sys.argv[1], sys.argv[2:]
467+
wrong = []
468+
for wheel in wheels:
469+
version_py = zipfile.ZipFile(wheel).read("executorch/version.py").decode()
470+
built = re.search(r"^git_version: .* = '(\w+)'", version_py, re.MULTILINE)
471+
if not built or built.group(1) != commit:
472+
wrong.append(f"{wheel} ({built.group(1) if built else 'no commit'})")
473+
if wrong:
474+
sys.exit(f"FAIL: not built from the component's {commit}: {', '.join(wrong)}")
475+
print(f"OK: all {len(wheels)} wheels were built from {commit}")
476+
PY
477+
}
478+
479+
wheel() {
480+
check_wheels "${3:?${usage}}" "${4:?${usage}}"
481+
}
482+
483+
rehearse() {
484+
local today output listing commit day version
485+
today=$(date -u +%Y%m%d)
486+
output=$( (check_wheels 1.6.0 0) 2>&1 || true)
487+
if [[ "${output}" != *"is not a dev version"* ]]; then
488+
echo "FAIL: the wheel check did not refuse 1.6.0: ${output}" >&2
489+
exit 1
490+
fi
491+
output=$( (check_wheels "1.6.0-dev.${today}" 0) 2>&1 || true)
492+
if [[ "${output}" != *"is today's nightly"* ]]; then
493+
echo "FAIL: the wheel check did not refuse today's nightly: ${output}" >&2
494+
exit 1
495+
fi
496+
echo "OK: the wheel check refuses a version that is not a dev version and today's nightly"
497+
listing=$(curl -sSf --retry 3 "${nightly_index}/executorch/")
498+
for commit in $(git rev-list --first-parent --since=60.days origin/nightly); do
499+
day=$(TZ=UTC git log -1 --format=%cd --date=format-local:%Y%m%d "${commit}")
500+
version="$(git show "${commit}:version.txt")-dev.${day}"
501+
if [[ "${day}" != "${today}" && -z "$(missing_wheels "${version}" "${listing}")" ]]; then
502+
check_wheels "${version}" "${commit}"
503+
return
504+
fi
505+
done
506+
echo "::warning::no nightly of the last 60 days has every wheel; the dev wheel check went unrehearsed."
507+
}
508+
509+
torch() {
510+
local version_file="${dir}/component/executorch/VERSION" requirement index target platform python
511+
requirement=$(sed -n 's/^torch_requirement: *//p' "${version_file}")
512+
index=$(sed -n 's/^torch_index: *//p' "${version_file}")
513+
target=$(mktemp -d)
514+
mkdir -p "${dir}/logs"
515+
for platform in "${wheel_platforms[@]}"; do
516+
for python in "${wheel_pythons[@]}"; do
517+
logged "${dir}/logs/torch-cp${python}-${platform}.log" python -m pip install --dry-run \
518+
--no-deps --only-binary=:all: --platform "${platform}" \
519+
--python-version "3.${python#3}" --implementation cp --target "${target}" \
520+
--index-url "${index}" "${requirement}"
521+
done
522+
done
523+
echo "OK: ${requirement} resolves from ${index} for CPython ${wheel_pythons[*]} on ${wheel_platforms[*]}"
524+
}
525+
398526
# Runs a build on its emulator: build dir, target, log, then idf.py arguments.
399527
run_firmware() {
400528
local build=$1 target=$2 log=$3
@@ -429,5 +557,8 @@ case "${mode}" in
429557
build) build "$@" ;;
430558
fetch) fetch "$@" ;;
431559
registry) registry "$@" ;;
560+
wheel) wheel "$@" ;;
561+
rehearse) rehearse ;;
562+
torch) torch ;;
432563
*) echo "unknown mode ${mode}; ${usage}" >&2; exit 1 ;;
433564
esac

‎.github/workflows/nightly-espressif-idf.yml‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,31 @@ jobs:
5050
source .ci/scripts/utils.sh
5151
install_executorch --use-pt-pinned-commit --minimal
5252
bash .ci/scripts/test_espressif_idf_nightly.sh prepare "${RUNNER_ARTIFACT_DIR}"
53+
bash .ci/scripts/test_espressif_idf_nightly.sh torch "${RUNNER_ARTIFACT_DIR}"
5354
# Runs the release stamp's checks, which publishing otherwise first runs
5455
# at a real tag, at a throwaway local one.
5556
git tag -f "v$(cat version.txt)"
5657
bash examples/espressif/build_idf_component.sh --version --version-suffix ""
5758
59+
# The dev versions' wheel check, which publishing otherwise first runs on a
60+
# dispatch from the nightly branch.
61+
dev-wheel-check:
62+
name: Rehearse the dev version's wheel check
63+
runs-on: ubuntu-22.04
64+
steps:
65+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
66+
with:
67+
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
68+
persist-credentials: false
69+
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
70+
with:
71+
python-version: '3.11'
72+
- run: |
73+
set -euo pipefail
74+
git fetch -q --shallow-since='60 days ago' origin \
75+
+refs/heads/nightly:refs/remotes/origin/nightly
76+
bash .ci/scripts/test_espressif_idf_nightly.sh rehearse "${RUNNER_TEMP}/wheel"
77+
5878
registry-dry-run:
5979
name: Registry validation (upload --dry-run)
6080
needs: [docker-image, prepare]

‎.github/workflows/publish-espressif-idf.yml‎

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
name: Publish ESP-IDF component
22

33
# Publishes pytorch/executorch to the ESP Component Registry: RC tags to the
4-
# staging registry, and release and respin tags to staging and then
5-
# production; manual runs validate without uploading unless told otherwise.
6-
# The archive is built and tested on the ESP-IDF releases the component
7-
# supports before any upload, and each upload is followed by a consumer build
8-
# that resolves the version from that registry. See the release runbook in
4+
# staging registry, release and respin tags to staging and then production,
5+
# and on demand a dev version of a nightly branch commit for early adopters;
6+
# other manual runs validate without uploading unless told otherwise. The
7+
# archive is built and tested on the ESP-IDF releases the component supports
8+
# before any upload, and each upload is followed by a consumer build that
9+
# resolves the version from that registry. See the release runbook in
910
# examples/espressif/README.md.
1011

1112
on:
@@ -15,7 +16,7 @@ on:
1516
workflow_dispatch:
1617
inputs:
1718
version_suffix:
18-
description: 'Version suffix: empty at a release tag, -rc.N at an RC tag, ~N at a respin tag vX.Y.Z-esp-idf.N'
19+
description: 'Version suffix: empty at a release tag, -rc.N at an RC tag, ~N at a respin tag vX.Y.Z-esp-idf.N, -dev for the dev version of the nightly branch'
1920
type: string
2021
default: ''
2122
registry:
@@ -62,6 +63,7 @@ jobs:
6263
shell: bash
6364
env:
6465
EVENT: ${{ github.event_name }}
66+
REF: ${{ github.ref }}
6567
REF_NAME: ${{ github.ref_name }}
6668
VERSION_SUFFIX: ${{ inputs.version_suffix }}
6769
REGISTRY: ${{ inputs.registry }}
@@ -87,8 +89,20 @@ jobs:
8789
fi
8890
;;
8991
workflow_dispatch)
90-
if [[ ! "${VERSION_SUFFIX}" =~ ^(-rc\.[1-9][0-9]*|~[1-9][0-9]*)?$ ]]; then
91-
echo "::error::version_suffix must be empty, -rc.N or ~N, not '${VERSION_SUFFIX}'."
92+
if [[ ! "${VERSION_SUFFIX}" =~ ^(-rc\.[1-9][0-9]*|~[1-9][0-9]*|-dev)?$ ]]; then
93+
echo "::error::version_suffix must be empty, -rc.N, ~N or -dev, not '${VERSION_SUFFIX}'."
94+
exit 1
95+
fi
96+
# A dev version's users install the nightly wheel of its commit.
97+
if [[ "${VERSION_SUFFIX}" == -dev && "${REF}" != refs/heads/nightly ]]; then
98+
echo "::error::a dev version is published from the nightly branch, not ${REF}."
99+
exit 1
100+
fi
101+
# Keeps the nightly branch to dev versions. This runs from the
102+
# dispatched ref's copy of the workflow, so the environment's
103+
# reviewers check what that copy does.
104+
if [[ "${REF}" == refs/heads/nightly && "${VERSION_SUFFIX}" != -dev ]]; then
105+
echo "::error::the nightly branch publishes dev versions only, with version_suffix -dev."
92106
exit 1
93107
fi
94108
if [[ "${VERSION_SUFFIX}" == -rc.* && "${REGISTRY}" == production ]]; then
@@ -145,22 +159,32 @@ jobs:
145159
unset SCCACHE_BUCKET SCCACHE_S3_KEY_PREFIX
146160
CONDA_ENV=$(conda env list --json | jq -r '.envs | .[-1]')
147161
conda activate "${CONDA_ENV}"
162+
suffix="${{ needs.plan.outputs.suffix }}"
163+
# A tag names its version, and a dispatch appends its suffix to
164+
# version.txt, except that -dev also takes the commit's date.
165+
expected="${{ needs.plan.outputs.version }}"
166+
expected="${expected:-$(cat version.txt)${suffix}}"
167+
# Before the build: a dev version's users install the nightly wheels of
168+
# its commit.
169+
if [[ "${suffix}" == -dev ]]; then
170+
expected=$(bash examples/espressif/build_idf_component.sh --version --version-suffix -dev)
171+
bash .ci/scripts/test_espressif_idf_nightly.sh wheel "${RUNNER_ARTIFACT_DIR}" \
172+
"${expected}" "$(git rev-parse HEAD)"
173+
fi
148174
source .ci/scripts/utils.sh
149175
install_executorch --use-pt-pinned-commit --minimal
150176
if [[ "${{ needs.plan.outputs.rehearsal }}" == true ]]; then
151177
# A pull request rehearses the release stamp at a throwaway local tag.
152178
git tag -f "v$(cat version.txt)"
153179
fi
154-
# A tag names its version; a dispatch appends its suffix to version.txt.
155-
expected="${{ needs.plan.outputs.version }}"
156-
expected="${expected:-$(cat version.txt)${{ needs.plan.outputs.suffix }}}"
157180
bash .ci/scripts/test_espressif_idf_nightly.sh prepare "${RUNNER_ARTIFACT_DIR}" \
158-
--version-suffix "${{ needs.plan.outputs.suffix }}"
181+
--version-suffix "${suffix}"
159182
version=$(cat "${RUNNER_ARTIFACT_DIR}/version")
160183
if [[ "${version}" != "${expected}" ]]; then
161184
echo "FAIL: generated version ${version}, expected ${expected}" >&2
162185
exit 1
163186
fi
187+
bash .ci/scripts/test_espressif_idf_nightly.sh torch "${RUNNER_ARTIFACT_DIR}"
164188
echo "Packed pytorch/executorch ${version}"
165189
# Nothing downstream reads the unpacked component.
166190
rm -r "${RUNNER_ARTIFACT_DIR}/component"

‎examples/espressif/README.md‎

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ both with `executorch_add_model` and `executorch_add_kernels` (see the
4343
component's `README.md`). Application pipelines built on the runtime
4444
(for example wake word front ends and detectors) stay with the
4545
application.
46-
Consumers need ESP-IDF, plus the `executorch` Python package of the
47-
same release to make kernel bundles — no host CMake build, no flatc.
46+
Consumers need ESP-IDF, plus the `executorch` Python package the
47+
component was built from to make kernel bundles (see the component's
48+
`README.md`) — no host CMake build, no flatc.
4849
`idf_component_smoke/` is a minimal consumer that CI generates, builds
4950
and runs on the emulator (`.ci/scripts/test_espressif_idf_component.sh`).
5051
`idf_component_consumer/` builds the same app from the packed component
@@ -87,6 +88,16 @@ serves the tested files, and runs it on the emulator.
8788
cannot hold `~`); the tag publishes it to staging, then production. A
8889
release whose publishing failed in CI is published as a respin once the
8990
CI is fixed.
91+
- A dev version, `X.Y.Z-dev.YYYYMMDD`, lets projects use the component
92+
before a release. Run the workflow on the `nightly` branch with
93+
`version_suffix` `-dev`, `registry` `production` and `dry_run` cleared,
94+
between 00:00 UTC and the next nightly (around 11:30 UTC), so that it
95+
publishes the last nightly of a finished day. Projects resolve from
96+
production, where a version range picks up a pre-release only if it opts
97+
in. The run publishes only if that day's ExecuTorch nightly wheels, for
98+
every platform and Python, were built from the same commit, because
99+
projects install them to make their kernel bundles. Before the first dev
100+
upload, run it once with `dry_run` left set, so its packing has run.
90101
- A manual run only validates unless `dry_run` is cleared. With `registry`
91102
`production`, it uploads to staging first. A run that uploads nothing
92103
rehearses the staging upload with `--dry-run`.
@@ -106,23 +117,31 @@ names this repository, this workflow and that environment, so no other job
106117
can upload with the repository's GitHub identity. Before approving an upload,
107118
check that the run's ref and commit are the release's announced tag and
108119
commit, or for a respin, that its tag's commit is on `release/X.Y` and
109-
its changes since `vX.Y.Z` were reviewed. Before approving the staging upload,
110-
dispatch the nightly matrix (`nightly-espressif-idf.yml`) on the tag and
111-
wait for its macOS and Windows configure jobs to pass; a failure on
112-
ESP-IDF master, which breaks on its own schedule, is advisory. Approve the
113-
production upload once `executorch` X.Y.Z is on PyPI, since a project
114-
needs it to make kernel bundles, and the release owner has built a
115-
project against the version on staging.
120+
its changes since `vX.Y.Z` were reviewed. A dev version's run comes from
121+
the `nightly` branch, whose copy of this workflow is main's and enforces
122+
its own limits, so before approving one, also review what changed in
123+
`publish-espressif-idf.yml` and `.ci/scripts/upload_espressif_idf_component.sh`
124+
since the last approved dev run. Before approving the staging upload of a
125+
release or RC, dispatch the nightly matrix (`nightly-espressif-idf.yml`) on
126+
the tag and wait for its macOS and Windows configure jobs to pass; a
127+
failure on ESP-IDF master, which breaks on its own schedule, is advisory.
128+
A dev version has only its own run's checks. Approve the production upload
129+
of a release once `executorch` X.Y.Z is on PyPI, since a project needs it
130+
to make kernel bundles, and the release owner has built a project against
131+
the version on staging; a dev version's run has already checked its
132+
nightly wheels.
116133

117134
The one-time setup goes in this order, because GitHub creates a missing
118135
environment, unprotected, as soon as a workflow names it:
119136

120137
1. Add rulesets that let only release managers create, update or delete
121138
`v*` tags, since the environment trusts them, and `release/*` branches,
122-
which respin tags must be on.
139+
which respin tags must be on, and only the account that pushes the
140+
nightly branch update or delete `nightly`, which the environment trusts
141+
for dev versions.
123142
2. Create the `esp-component-registry` environment with required
124143
reviewers, self-review prevented, no admin bypass, and deployments
125-
limited to `v*` tags.
144+
limited to `v*` tags, plus `nightly` before the first dev version.
126145
3. Create the `pytorch` namespace on the staging registry, which takes
127146
namespace requests of its own, apart from the production registry's.
128147
4. On each registry, add a trusted uploader to `pytorch/executorch` (in

0 commit comments

Comments
 (0)