name: Build And Package on: push: tags: - "v*" jobs: build-package: runs-on: ${{ matrix.os }} env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest] steps: - name: Checkout source uses: actions/checkout@v5 - name: Setup Python uses: actions/setup-python@v6 with: python-version: "3.12" - name: Install system build tools if: runner.os == 'Linux' run: | sudo apt-get update sudo apt-get install -y build-essential - name: Install compile dependencies run: | python -m pip install --upgrade pip pip install cython setuptools wheel - name: Run Cython compile run: | python scripts/compile.py - name: Prepare package and archive run: | python - <<'PY' import os import shutil import tarfile import zipfile import sys from pathlib import Path root = Path.cwd() package_dir = root / "package" dist_dir = root / "dist" for d in [package_dir, dist_dir]: if d.exists(): shutil.rmtree(d) d.mkdir(parents=True, exist_ok=True) # Define directories with compiled artifacts compile_dirs = ["app/services", "app/native/wndb", "app/algorithms"] # Global ignore list ignore_names = { ".git", ".github", "__pycache__", ".pytest_cache", ".mypy_cache", ".venv", "venv", "temp", "tests", "package", "dist", } def ignore_func(directory, names): rel_dir = os.path.relpath(directory, root).replace("\\", "/") is_in_compile_path = any(rel_dir.startswith(d) for d in compile_dirs) ignored = [] for name in names: if name in ignore_names or name.endswith(".pyc"): ignored.append(name) # Exclude source .py files only in compiled directories elif is_in_compile_path and name.endswith(".py"): ignored.append(name) return ignored for item in root.iterdir(): if item.name in ignore_names: continue target = package_dir / item.name if item.is_dir(): shutil.copytree(item, target, ignore=ignore_func) else: shutil.copy2(item, target) # Safety guard: ensure no .github directory remains github_paths = [p for p in package_dir.rglob(".github") if p.is_dir()] for p in github_paths: shutil.rmtree(p, ignore_errors=True) sha = os.environ["GITHUB_SHA"] run_os = os.environ["RUNNER_OS"].lower() if run_os == "windows": archive_path = dist_dir / f"tjwater-server-{run_os}-{sha}.zip" with zipfile.ZipFile(archive_path, "w", compression=zipfile.ZIP_DEFLATED) as zf: for f in package_dir.rglob("*"): if f.is_file(): zf.write(f, f.relative_to(package_dir)) else: archive_path = dist_dir / f"tjwater-server-{run_os}-{sha}.tar.gz" with tarfile.open(archive_path, "w:gz") as tf: tf.add(package_dir, arcname=".") print(f"Archive created: {archive_path}") PY shell: bash - name: Upload package artifact uses: actions/upload-artifact@v5 with: name: tjwater-server-package-${{ runner.os }} path: dist/* retention-days: 14