fix: 兼容脚本管理未解压上传包

This commit is contained in:
2026-07-31 17:46:55 +08:00
parent e063ed0692
commit 36338152d0
3 changed files with 26 additions and 4 deletions
+4 -2
View File
@@ -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
+2 -2
View File
@@ -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
+20
View File
@@ -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: