fix: 兼容脚本管理未解压上传包
This commit is contained in:
@@ -52,9 +52,9 @@ docker build -t interference-etl-runtime:1.1 .
|
|||||||
python scripts\build_offline_package.py
|
python scripts\build_offline_package.py
|
||||||
```
|
```
|
||||||
|
|
||||||
The generated `dist/InterferenceETL-offline-1.1.zip` contains `main.py` plus `openpyxl`, `et_xmlfile`, and `PyMySQL`. The builder verifies imports using the standard `python:3.13.11-slim` image, so the uploaded workspace does not need an online `pip install` or a custom runtime image. The ZIP is 325,489 bytes with SHA-256 `4F655D35F89A826F28A41578C9EE3E347CE31A27619D3D06AE0FD9587660DCAF`.
|
The generated `dist/InterferenceETL-offline-1.1.zip` contains `main.py`, a ZIP execution entry point, and `openpyxl`, `et_xmlfile`, and `PyMySQL`. The builder verifies both imports and ZIP execution using the standard `python:3.13.11-slim` image, so the uploaded workspace does not need an online `pip install` or a custom runtime image.
|
||||||
|
|
||||||
Create the project, then upload and extract the ZIP in its Script Management workspace. Use these project settings:
|
Create the project, then upload and extract the ZIP in its Script Management workspace. The normal file tree should contain `main.py` at `/workspace/main.py`. Use these project settings:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Name: InterferenceETL
|
Name: InterferenceETL
|
||||||
@@ -65,6 +65,8 @@ Run command: python main.py
|
|||||||
Timeout: 1800 seconds
|
Timeout: 1800 seconds
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If the server keeps the ZIP as one file instead of extracting it, use `python InterferenceETL-offline-1.1.zip` as the run command. The ZIP contains `__main__.py` for this mode.
|
||||||
|
|
||||||
Configure only the Metrix source settings in the project environment:
|
Configure only the Metrix source settings in the project environment:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
|||||||
@@ -22,9 +22,9 @@
|
|||||||
|
|
||||||
## 2026-07-31: Self-contained Script Management package
|
## 2026-07-31: Self-contained Script Management package
|
||||||
|
|
||||||
- `scripts/build_offline_package.py` copies the three runtime distributions from the verified dependency image, adds the application files, and creates a ZIP that Metrix can extract without preserving executable bits or symlinks.
|
- `scripts/build_offline_package.py` copies the three runtime distributions from the verified dependency image, adds the application files and `__main__.py`, and creates a ZIP that Metrix can extract without preserving executable bits or symlinks. The archive can also run directly as `python InterferenceETL-offline-1.1.zip` when a Script Management server stores the upload without extracting it.
|
||||||
- The builder runs an import check inside `python:3.13.11-slim`; the package therefore needs neither a custom server image nor online package installation.
|
- The builder runs an import check inside `python:3.13.11-slim`; the package therefore needs neither a custom server image nor online package installation.
|
||||||
- Current artifact: `dist/InterferenceETL-offline-1.1.zip`, 325,489 bytes, SHA-256 `4F655D35F89A826F28A41578C9EE3E347CE31A27619D3D06AE0FD9587660DCAF`. The builder excludes bytecode caches, and the ignored `dist/` directory is the only location for this generated package.
|
- The builder excludes bytecode caches, and the ignored `dist/` directory is the only location for this generated package.
|
||||||
|
|
||||||
## 2026-07-31: Fixed CGI and database configuration
|
## 2026-07-31: Fixed CGI and database configuration
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ DEFAULT_IMAGE = "interference-etl-runtime:1.1"
|
|||||||
DEFAULT_BASE_IMAGE = "python:3.13.11-slim"
|
DEFAULT_BASE_IMAGE = "python:3.13.11-slim"
|
||||||
DEFAULT_OUTPUT = PROJECT_ROOT / "dist" / "InterferenceETL-offline-1.1.zip"
|
DEFAULT_OUTPUT = PROJECT_ROOT / "dist" / "InterferenceETL-offline-1.1.zip"
|
||||||
PACKAGE_FILES = ("main.py", "requirements.txt", "README.md")
|
PACKAGE_FILES = ("main.py", "requirements.txt", "README.md")
|
||||||
|
PACKAGE_ENTRYPOINT = "from main import main\nraise SystemExit(main())\n"
|
||||||
|
|
||||||
COPY_DEPENDENCIES = r"""
|
COPY_DEPENDENCIES = r"""
|
||||||
from importlib.metadata import distribution
|
from importlib.metadata import distribution
|
||||||
@@ -56,6 +57,7 @@ def build(output: Path, runtime_image: str, base_image: str) -> Path:
|
|||||||
)
|
)
|
||||||
for name in PACKAGE_FILES:
|
for name in PACKAGE_FILES:
|
||||||
shutil.copy2(PROJECT_ROOT / name, staging / name)
|
shutil.copy2(PROJECT_ROOT / name, staging / name)
|
||||||
|
(staging / "__main__.py").write_text(PACKAGE_ENTRYPOINT, encoding="utf-8")
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
[
|
[
|
||||||
"docker",
|
"docker",
|
||||||
@@ -74,6 +76,24 @@ def build(output: Path, runtime_image: str, base_image: str) -> Path:
|
|||||||
],
|
],
|
||||||
check=True,
|
check=True,
|
||||||
)
|
)
|
||||||
|
subprocess.run(
|
||||||
|
[
|
||||||
|
"docker",
|
||||||
|
"run",
|
||||||
|
"--rm",
|
||||||
|
"-e",
|
||||||
|
"PYTHONDONTWRITEBYTECODE=1",
|
||||||
|
"-v",
|
||||||
|
f"{staging}:/workspace:ro",
|
||||||
|
"-w",
|
||||||
|
"/workspace",
|
||||||
|
base_image,
|
||||||
|
"python",
|
||||||
|
"__main__.py",
|
||||||
|
"--help",
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
if output.exists():
|
if output.exists():
|
||||||
output.unlink()
|
output.unlink()
|
||||||
with zipfile.ZipFile(output, "w", compression=zipfile.ZIP_DEFLATED, compresslevel=9) as archive:
|
with zipfile.ZipFile(output, "w", compression=zipfile.ZIP_DEFLATED, compresslevel=9) as archive:
|
||||||
|
|||||||
Reference in New Issue
Block a user