Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 89ff465

Browse filesBrowse files
authored
feat(esptool): Upgrade to esptool v5 (#11433)
* feat(esptool): Upgrade to esptool v5 * fix(script): Update script for better handling of esptool * fix(script): Get proper download url * fix(script): Apply copilot suggestions
1 parent e9813c6 commit 89ff465
Copy full SHA for 89ff465

File tree

Expand file treeCollapse file tree

3 files changed

+277
-41
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+277
-41
lines changed

‎.github/scripts/update_esptool.py

Copy file name to clipboard
+236Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
#!/usr/bin/env python3
2+
3+
# This script is used to re-package the esptool if needed and update the JSON file
4+
# for the Arduino ESP32 platform.
5+
#
6+
# The script has only been tested on macOS.
7+
#
8+
# For regular esptool releases, the generated packages already contain the correct permissions,
9+
# extensions and are uploaded to the GitHub release assets. In this case, the script will only
10+
# update the JSON file with the information from the GitHub release.
11+
#
12+
# The script can be used in two modes:
13+
# 1. Local build: The build artifacts must be already downloaded and extracted in the base_folder.
14+
# This is useful for esptool versions that are not yet released and that are grabbed from the
15+
# GitHub build artifacts.
16+
# 2. Release build: The script will get the release information from GitHub and update the JSON file.
17+
# This is useful for esptool versions that are already released and that are uploaded to the
18+
# GitHub release assets.
19+
#
20+
# For local build, the artifacts must be already downloaded and extracted in the base_folder
21+
# set with the -l option.
22+
# For example, a base folder "esptool" should contain the following folders extracted directly
23+
# from the GitHub build artifacts:
24+
# esptool/esptool-linux-aarch64
25+
# esptool/esptool-linux-amd64
26+
# esptool/esptool-linux-armv7
27+
# esptool/esptool-macos-amd64
28+
# esptool/esptool-macos-arm64
29+
# esptool/esptool-windows-amd64
30+
31+
import argparse
32+
import json
33+
import os
34+
import shutil
35+
import stat
36+
import tarfile
37+
import zipfile
38+
import hashlib
39+
import requests
40+
from pathlib import Path
41+
42+
def compute_sha256(filepath):
43+
sha256 = hashlib.sha256()
44+
with open(filepath, "rb") as f:
45+
for block in iter(lambda: f.read(4096), b""):
46+
sha256.update(block)
47+
return f"SHA-256:{sha256.hexdigest()}"
48+
49+
def get_file_size(filepath):
50+
return os.path.getsize(filepath)
51+
52+
def update_json_for_host(tmp_json_path, version, host, url, archiveFileName, checksum, size):
53+
with open(tmp_json_path) as f:
54+
data = json.load(f)
55+
56+
for pkg in data.get("packages", []):
57+
for tool in pkg.get("tools", []):
58+
if tool.get("name") == "esptool_py":
59+
tool["version"] = version
60+
61+
if url is None:
62+
# If the URL is not set, we need to find the old URL and update it
63+
for system in tool.get("systems", []):
64+
if system.get("host") == host:
65+
url = system.get("url").replace(system.get("archiveFileName"), archiveFileName)
66+
break
67+
else:
68+
print(f"No old URL found for host {host}. Using empty URL.")
69+
url = ""
70+
71+
# Preserve existing systems order and update or append the new system
72+
systems = tool.get("systems", [])
73+
system_updated = False
74+
for i, system in enumerate(systems):
75+
if system.get("host") == host:
76+
systems[i] = {
77+
"host": host,
78+
"url": url,
79+
"archiveFileName": archiveFileName,
80+
"checksum": checksum,
81+
"size": str(size),
82+
}
83+
system_updated = True
84+
break
85+
86+
if not system_updated:
87+
systems.append({
88+
"host": host,
89+
"url": url,
90+
"archiveFileName": archiveFileName,
91+
"checksum": checksum,
92+
"size": str(size),
93+
})
94+
tool["systems"] = systems
95+
96+
with open(tmp_json_path, "w") as f:
97+
json.dump(data, f, indent=2, sort_keys=False, ensure_ascii=False)
98+
f.write("\n")
99+
100+
def update_tools_dependencies(tmp_json_path, version):
101+
with open(tmp_json_path) as f:
102+
data = json.load(f)
103+
104+
for pkg in data.get("packages", []):
105+
for platform in pkg.get("platforms", []):
106+
for dep in platform.get("toolsDependencies", []):
107+
if dep.get("name") == "esptool_py":
108+
dep["version"] = version
109+
110+
with open(tmp_json_path, "w") as f:
111+
json.dump(data, f, indent=2, sort_keys=False, ensure_ascii=False)
112+
f.write("\n")
113+
114+
def create_archives(version, base_folder):
115+
archive_files = []
116+
117+
for dirpath in Path(base_folder).glob("esptool-*"):
118+
if not dirpath.is_dir():
119+
continue
120+
121+
base = dirpath.name[len("esptool-"):]
122+
123+
if "windows" in dirpath.name:
124+
zipfile_name = f"esptool-v{version}-{base}.zip"
125+
print(f"Creating {zipfile_name} from {dirpath} ...")
126+
with zipfile.ZipFile(zipfile_name, "w", zipfile.ZIP_DEFLATED) as zipf:
127+
for root, _, files in os.walk(dirpath):
128+
for file in files:
129+
full_path = os.path.join(root, file)
130+
zipf.write(full_path, os.path.relpath(full_path, start=dirpath))
131+
archive_files.append(zipfile_name)
132+
else:
133+
tarfile_name = f"esptool-v{version}-{base}.tar.gz"
134+
print(f"Creating {tarfile_name} from {dirpath} ...")
135+
for root, dirs, files in os.walk(dirpath):
136+
for name in dirs + files:
137+
os.chmod(os.path.join(root, name), stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
138+
stat.S_IRGRP | stat.S_IXGRP |
139+
stat.S_IROTH | stat.S_IXOTH)
140+
with tarfile.open(tarfile_name, "w:gz") as tar:
141+
tar.add(dirpath, arcname=dirpath.name)
142+
archive_files.append(tarfile_name)
143+
144+
return archive_files
145+
146+
def determine_hosts(archive_name):
147+
if "linux-amd64" in archive_name:
148+
return ["x86_64-pc-linux-gnu"]
149+
elif "linux-armv7" in archive_name:
150+
return ["arm-linux-gnueabihf"]
151+
elif "linux-aarch64" in archive_name:
152+
return ["aarch64-linux-gnu"]
153+
elif "macos-amd64" in archive_name:
154+
return ["x86_64-apple-darwin"]
155+
elif "macos-arm64" in archive_name:
156+
return ["arm64-apple-darwin"]
157+
elif "windows-amd64" in archive_name:
158+
return ["x86_64-mingw32", "i686-mingw32"]
159+
else:
160+
return []
161+
162+
def update_json_from_local_build(tmp_json_path, version, base_folder, archive_files):
163+
for archive in archive_files:
164+
print(f"Processing archive: {archive}")
165+
hosts = determine_hosts(archive)
166+
if not hosts:
167+
print(f"Skipping unknown archive type: {archive}")
168+
continue
169+
170+
archive_path = Path(archive)
171+
checksum = compute_sha256(archive_path)
172+
size = get_file_size(archive_path)
173+
174+
for host in hosts:
175+
update_json_for_host(tmp_json_path, version, host, None, archive_path.name, checksum, size)
176+
177+
def update_json_from_release(tmp_json_path, version, release_info):
178+
assets = release_info.get("assets", [])
179+
for asset in assets:
180+
if (asset.get("name").endswith(".tar.gz") or asset.get("name").endswith(".zip")) and "esptool" in asset.get("name"):
181+
asset_fname = asset.get("name")
182+
print(f"Processing asset: {asset_fname}")
183+
hosts = determine_hosts(asset_fname)
184+
if not hosts:
185+
print(f"Skipping unknown archive type: {asset_fname}")
186+
continue
187+
188+
asset_url = asset.get("browser_download_url")
189+
asset_checksum = asset.get("digest")
190+
asset_size = asset.get("size")
191+
if asset_checksum is None:
192+
asset_checksum = ""
193+
print(f"Asset {asset_fname} has no checksum. Please set the checksum in the JSON file.")
194+
195+
for host in hosts:
196+
update_json_for_host(tmp_json_path, version, host, asset_url, asset_fname, asset_checksum, asset_size)
197+
198+
def get_release_info(version):
199+
url = f"https://api.github.com/repos/espressif/esptool/releases/tags/v{version}"
200+
response = requests.get(url)
201+
response.raise_for_status()
202+
return response.json()
203+
204+
def main():
205+
parser = argparse.ArgumentParser(description="Repack esptool and update JSON metadata.")
206+
parser.add_argument("version", help="Version of the esptool (e.g. 5.0.dev1)")
207+
parser.add_argument("-l", "--local", dest="base_folder", help="Enable local build mode and set the base folder with unpacked artifacts")
208+
args = parser.parse_args()
209+
210+
script_dir = Path(__file__).resolve().parent
211+
json_path = (script_dir / "../../package/package_esp32_index.template.json").resolve()
212+
tmp_json_path = Path(str(json_path) + ".tmp")
213+
shutil.copy(json_path, tmp_json_path)
214+
215+
local_build = args.base_folder is not None
216+
217+
if local_build:
218+
os.chdir(args.base_folder)
219+
os.environ['COPYFILE_DISABLE'] = 'true' # this disables including resource forks in tar files on macOS
220+
# Clear any existing archive files
221+
for file in Path(args.base_folder).glob("esptool-*.*"):
222+
file.unlink()
223+
archive_files = create_archives(args.version, args.base_folder)
224+
update_json_from_local_build(tmp_json_path, args.version, args.base_folder, archive_files)
225+
else:
226+
release_info = get_release_info(args.version)
227+
update_json_from_release(tmp_json_path, args.version, release_info)
228+
229+
print(f"Updating esptool version fields to {args.version}")
230+
update_tools_dependencies(tmp_json_path, args.version)
231+
232+
shutil.move(tmp_json_path, json_path)
233+
print(f"Done. JSON updated at {json_path}")
234+
235+
if __name__ == "__main__":
236+
main()

‎package/package_esp32_index.template.json

Copy file name to clipboardExpand all lines: package/package_esp32_index.template.json
+35-35Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
{
8282
"packager": "esp32",
8383
"name": "esptool_py",
84-
"version": "4.9.dev3"
84+
"version": "5.0.dev1"
8585
},
8686
{
8787
"packager": "esp32",
@@ -469,56 +469,56 @@
469469
},
470470
{
471471
"name": "esptool_py",
472-
"version": "4.9.dev3",
472+
"version": "5.0.dev1",
473473
"systems": [
474474
{
475-
"host": "x86_64-pc-linux-gnu",
476-
"url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-linux-amd64.tar.gz",
477-
"archiveFileName": "esptool-v4.9.dev3-linux-amd64.tar.gz",
478-
"checksum": "SHA-256:4ecaf51836cbf4ea3c19840018bfef3b0b8cd8fc3c95f6e1e043ca5bbeab9bf0",
479-
"size": "64958202"
475+
"host": "aarch64-linux-gnu",
476+
"url": "https://github.com/espressif/arduino-esp32/releases/download/3.2.0/esptool-v5.0.dev1-linux-aarch64.tar.gz",
477+
"archiveFileName": "esptool-v5.0.dev1-linux-aarch64.tar.gz",
478+
"checksum": "SHA-256:bfafa7a7723ebbabfd8b6e3ca5ae00bfead0331de923754aeddb43b2c116a078",
479+
"size": "58241736"
480480
},
481481
{
482-
"host": "arm-linux-gnueabihf",
483-
"url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-linux-armv7.tar.gz",
484-
"archiveFileName": "esptool-v4.9.dev3-linux-armv7.tar.gz",
485-
"checksum": "SHA-256:fff818573bce483ee793ac83c8211f6abf764aa3350f198228859f696a0a0b36",
486-
"size": "31530030"
482+
"host": "x86_64-pc-linux-gnu",
483+
"url": "https://github.com/espressif/arduino-esp32/releases/download/3.2.0/esptool-v5.0.dev1-linux-amd64.tar.gz",
484+
"archiveFileName": "esptool-v5.0.dev1-linux-amd64.tar.gz",
485+
"checksum": "SHA-256:acd0486e96586b99d053a1479acbbbfcae8667227c831cdc53a171f9ccfa27ee",
486+
"size": "100740042"
487487
},
488488
{
489-
"host": "aarch64-linux-gnu",
490-
"url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-linux-aarch64.tar.gz",
491-
"archiveFileName": "esptool-v4.9.dev3-linux-aarch64.tar.gz",
492-
"checksum": "SHA-256:5b274bdff2f62e6a07c3c1dfa51b1128924621f661747eca3dbe0f77972f2f06",
493-
"size": "33663882"
489+
"host": "arm-linux-gnueabihf",
490+
"url": "https://github.com/espressif/arduino-esp32/releases/download/3.2.0/esptool-v5.0.dev1-linux-armv7.tar.gz",
491+
"archiveFileName": "esptool-v5.0.dev1-linux-armv7.tar.gz",
492+
"checksum": "SHA-256:ea77a38681506761bbb7b0b39c130811ed565667b67ebbdb4d6dcc6cb6e07368",
493+
"size": "53451939"
494494
},
495495
{
496496
"host": "x86_64-apple-darwin",
497-
"url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-macos-amd64.tar.gz",
498-
"archiveFileName": "esptool-v4.9.dev3-macos-amd64.tar.gz",
499-
"checksum": "SHA-256:c733c83b58fcf5f642fbb2fddb8ff24640c2c785126cba0821fb70c4a5ceea7a",
500-
"size": "32767836"
497+
"url": "https://github.com/espressif/arduino-esp32/releases/download/3.2.0/esptool-v5.0.dev1-macos-amd64.tar.gz",
498+
"archiveFileName": "esptool-v5.0.dev1-macos-amd64.tar.gz",
499+
"checksum": "SHA-256:900a8e90731208bee96647e0e207a43612b9452c2120c4fdc0ff4c6be226257b",
500+
"size": "59631998"
501501
},
502502
{
503503
"host": "arm64-apple-darwin",
504-
"url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-macos-arm64.tar.gz",
505-
"archiveFileName": "esptool-v4.9.dev3-macos-arm64.tar.gz",
506-
"checksum": "SHA-256:83c195a15981e6a5e7a130db2ccfb21e2d8093912e5b003681f9a5abadd71af7",
507-
"size": "30121441"
504+
"url": "https://github.com/espressif/arduino-esp32/releases/download/3.2.0/esptool-v5.0.dev1-macos-arm64.tar.gz",
505+
"archiveFileName": "esptool-v5.0.dev1-macos-arm64.tar.gz",
506+
"checksum": "SHA-256:3653f4de73cb4fc6a25351eaf663708e91c65ae3265d75bd54ca4315a4350bb4",
507+
"size": "56349992"
508508
},
509509
{
510-
"host": "i686-mingw32",
511-
"url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-win64.zip",
512-
"archiveFileName": "esptool-v4.9.dev3-win64.zip",
513-
"checksum": "SHA-256:890051a4fdc684ff6f4af18d0bb27d274ca940ee0eef716a9455f8c64b25b215",
514-
"size": "36072564"
510+
"host": "x86_64-mingw32",
511+
"url": "https://github.com/espressif/arduino-esp32/releases/download/3.2.0/esptool-v5.0.dev1-win64.zip",
512+
"archiveFileName": "esptool-v5.0.dev1-win64.zip",
513+
"checksum": "SHA-256:1e8fd89645daf94f2d4406ec73c9004e617ea921079515f9fd749205eece4d6d",
514+
"size": "59102658"
515515
},
516516
{
517-
"host": "x86_64-mingw32",
518-
"url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-win64.zip",
519-
"archiveFileName": "esptool-v4.9.dev3-win64.zip",
520-
"checksum": "SHA-256:890051a4fdc684ff6f4af18d0bb27d274ca940ee0eef716a9455f8c64b25b215",
521-
"size": "36072564"
517+
"host": "i686-mingw32",
518+
"url": "https://github.com/espressif/arduino-esp32/releases/download/3.2.0/esptool-v5.0.dev1-win64.zip",
519+
"archiveFileName": "esptool-v5.0.dev1-win64.zip",
520+
"checksum": "SHA-256:1e8fd89645daf94f2d4406ec73c9004e617ea921079515f9fd749205eece4d6d",
521+
"size": "59102658"
522522
}
523523
]
524524
},

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.