릴리즈: 0.0.12 버전 정정 #14
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Product Release | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| - "!v*-launcher" | |
| env: | |
| PYTHON_VERSION: "3.12" | |
| PYTHON_RUNTIME_VERSION: "3.12.12" | |
| PYTHON_RUNTIME_ASSET: python-runtime-win-x64.zip | |
| RELEASE_MANIFEST_ASSET: release-manifest.json | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| package_version: ${{ steps.package.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v6 | |
| with: | |
| enable-cache: true | |
| - name: Set up Python | |
| run: uv python install ${{ env.PYTHON_VERSION }} | |
| - name: Setup Node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: "22" | |
| cache: "npm" | |
| cache-dependency-path: editor/package-lock.json | |
| - name: Build editor | |
| working-directory: editor | |
| run: | | |
| npm ci | |
| npm run build | |
| - name: Verify packaged editor build | |
| run: | | |
| test -f src/codaro/webBuild/index.html | |
| test -d src/codaro/webBuild/_app | |
| - name: Run tests | |
| run: uv run --extra dev pytest tests/ -v --tb=short | |
| - name: Stage base curriculum into package | |
| run: | | |
| rm -rf src/codaro/curricula | |
| cp -r curricula src/codaro/curricula | |
| test -f src/codaro/curricula/python/__init__.py | |
| - name: Build wheel | |
| run: uv build | |
| - name: Read package version | |
| id: package | |
| run: | | |
| python - <<'PY' >> "$GITHUB_OUTPUT" | |
| import tomllib | |
| with open("pyproject.toml", "rb") as handle: | |
| version = tomllib.load(handle)["project"]["version"] | |
| print(f"version={version}") | |
| PY | |
| - name: Verify tag matches package version | |
| run: | | |
| if [ "${GITHUB_REF_NAME}" != "v${{ steps.package.outputs.version }}" ]; then | |
| echo "tag ${GITHUB_REF_NAME} does not match package version v${{ steps.package.outputs.version }}" >&2 | |
| exit 1 | |
| fi | |
| - name: Prepare package release assets | |
| run: mkdir -p release-assets | |
| - name: Generate package SPDX SBOM | |
| uses: anchore/sbom-action@v0 | |
| with: | |
| path: . | |
| format: spdx-json | |
| output-file: release-assets/codaro.spdx.json | |
| - name: Verify wheel includes editor frontend and base curriculum | |
| run: | | |
| python - <<'PY' | |
| from pathlib import Path | |
| import zipfile | |
| wheel = next(Path("dist").glob("codaro-*.whl")) | |
| with zipfile.ZipFile(wheel) as archive: | |
| names = set(archive.namelist()) | |
| if "codaro/webBuild/index.html" not in names: | |
| raise SystemExit("codaro/webBuild/index.html missing from wheel") | |
| if not any(name.startswith("codaro/webBuild/_app/") for name in names): | |
| raise SystemExit("codaro/webBuild/_app/ assets missing from wheel") | |
| if "codaro/curricula/python/__init__.py" not in names: | |
| raise SystemExit("codaro/curricula/python/__init__.py missing from wheel") | |
| lessonCount = sum( | |
| 1 for name in names | |
| if name.startswith("codaro/curricula/python/") and name.endswith(".yaml") | |
| ) | |
| if lessonCount == 0: | |
| raise SystemExit("codaro/curricula/python/*.yaml lessons missing from wheel") | |
| print(f"verified packaged editor frontend and {lessonCount} curriculum lessons in {wheel}") | |
| PY | |
| - name: Upload dist artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist/ | |
| - name: Upload package release assets | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: package-release-assets | |
| path: release-assets/ | |
| windows-release-assets: | |
| runs-on: windows-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v6 | |
| with: | |
| enable-cache: true | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Install managed Python runtime | |
| shell: pwsh | |
| run: uv python install $env:PYTHON_RUNTIME_VERSION | |
| - name: Package managed Python runtime | |
| shell: pwsh | |
| run: | | |
| $python = (uv python find $env:PYTHON_RUNTIME_VERSION).Trim() | |
| $runtimeRoot = Split-Path -Parent $python | |
| $stage = Join-Path $env:RUNNER_TEMP "codaro-python-runtime" | |
| $pythonStage = Join-Path $stage "python" | |
| if (Test-Path $stage) { | |
| Remove-Item -Recurse -Force $stage | |
| } | |
| New-Item -ItemType Directory -Force -Path $pythonStage | Out-Null | |
| Copy-Item -Path (Join-Path $runtimeRoot "*") -Destination $pythonStage -Recurse -Force | |
| # codaro 백엔드 런타임 의존성 + 커리큘럼 라이브러리를 런타임에 사전 설치한다. launcher provision은 | |
| # codaro wheel을 --no-deps로(오프라인) 설치하므로, 런타임이 의존성을 제공하지 않으면 (a) 백엔드가 | |
| # fastapi/pydantic 부재로 기동 실패하고, (b) 커리큘럼 레슨이 pandas/numpy/matplotlib 부재로 셀 실행 | |
| # 시 ModuleNotFoundError를 낸다. 셀은 백엔드 인터프리터에서 in-process로 실행되므로 레슨 라이브러리도 | |
| # 이 런타임에 있어야 한다. uv.lock 고정 버전을 curriculum extra 포함으로 export 해 설치한다. | |
| $runtimePython = Join-Path $pythonStage "python.exe" | |
| & $runtimePython -m ensurepip --upgrade | Out-Null | |
| $depsFile = Join-Path $env:RUNNER_TEMP "codaro-backend-deps.txt" | |
| uv export --no-dev --extra curriculum --no-emit-project --no-hashes --output-file $depsFile | |
| if ($LASTEXITCODE -ne 0) { throw "uv export of backend + curriculum dependencies failed" } | |
| & $runtimePython -m pip install --break-system-packages --disable-pip-version-check --no-warn-script-location -r $depsFile | |
| if ($LASTEXITCODE -ne 0) { throw "failed to pre-install backend + curriculum dependencies into runtime" } | |
| & $runtimePython -c "import fastapi, pydantic, uvicorn, yaml, requests; import pandas, numpy, matplotlib, sklearn, openpyxl; print('runtime backend + curriculum deps verified')" | |
| if ($LASTEXITCODE -ne 0) { throw "runtime backend + curriculum dependency verification failed" } | |
| New-Item -ItemType Directory -Force -Path "launcher/target/release" | Out-Null | |
| $runtimeArchive = "launcher/target/release/$($env:PYTHON_RUNTIME_ASSET)" | |
| Compress-Archive -Path (Join-Path $stage "python") -DestinationPath $runtimeArchive -Force | |
| $hash = (Get-FileHash $runtimeArchive -Algorithm SHA256).Hash.ToLower() | |
| "$hash $($env:PYTHON_RUNTIME_ASSET)" | Out-File -FilePath "$runtimeArchive.sha256" -Encoding utf8 | |
| - name: Build launcher release binary | |
| working-directory: launcher/codaro-launcher | |
| run: cargo build --release | |
| - name: Rename launcher binary | |
| shell: pwsh | |
| run: | | |
| Copy-Item "launcher/target/release/codaro-launcher.exe" "launcher/target/release/Codaro.exe" | |
| - name: Compute launcher SHA256 | |
| shell: pwsh | |
| run: | | |
| $hash = (Get-FileHash "launcher/target/release/Codaro.exe" -Algorithm SHA256).Hash.ToLower() | |
| "$hash Codaro.exe" | Out-File -FilePath "launcher/target/release/Codaro.exe.sha256" -Encoding utf8 | |
| - name: Generate launcher SPDX SBOM | |
| uses: anchore/sbom-action@v0 | |
| with: | |
| path: launcher/codaro-launcher | |
| format: spdx-json | |
| output-file: launcher/target/release/Codaro.exe.spdx.json | |
| - name: Upload Windows release assets | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: windows-release-assets | |
| path: | | |
| launcher/target/release/Codaro.exe | |
| launcher/target/release/Codaro.exe.sha256 | |
| launcher/target/release/Codaro.exe.spdx.json | |
| launcher/target/release/${{ env.PYTHON_RUNTIME_ASSET }} | |
| launcher/target/release/${{ env.PYTHON_RUNTIME_ASSET }}.sha256 | |
| release: | |
| needs: [build, windows-release-assets] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Download Windows release assets | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: windows-release-assets | |
| path: release-assets/ | |
| - name: Download package release assets | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: package-release-assets | |
| path: release-assets/ | |
| - name: Download backend dist | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist/ | |
| - name: Prepare backend wheel release asset | |
| id: backend_wheel | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| wheel_count="$(find dist -maxdepth 1 -name 'codaro-*.whl' | wc -l | tr -d ' ')" | |
| if [ "$wheel_count" != "1" ]; then | |
| echo "expected exactly one codaro wheel in dist, found $wheel_count" >&2 | |
| find dist -maxdepth 1 -type f -print >&2 | |
| exit 1 | |
| fi | |
| wheel_path="$(find dist -maxdepth 1 -name 'codaro-*.whl' -print -quit)" | |
| wheel_name="$(basename "$wheel_path")" | |
| wheel_sha="$(sha256sum "$wheel_path" | awk '{print $1}')" | |
| cp "$wheel_path" "release-assets/$wheel_name" | |
| printf '%s %s\n' "$wheel_sha" "$wheel_name" > "release-assets/$wheel_name.sha256" | |
| echo "name=$wheel_name" >> "$GITHUB_OUTPUT" | |
| echo "sha256=$wheel_sha" >> "$GITHUB_OUTPUT" | |
| - name: Build release manifest | |
| run: | | |
| python docs/skills/ops/tools/buildReleaseManifest.py \ | |
| --tag "${GITHUB_REF_NAME}" \ | |
| --repo "${GITHUB_REPOSITORY}" \ | |
| --package-version "${{ needs.build.outputs.package_version }}" \ | |
| --backend-wheel-url "https://github.com/${GITHUB_REPOSITORY}/releases/download/${GITHUB_REF_NAME}/${{ steps.backend_wheel.outputs.name }}" \ | |
| --backend-sha256 "${{ steps.backend_wheel.outputs.sha256 }}" \ | |
| --python-runtime-version "${PYTHON_RUNTIME_VERSION}" \ | |
| --python-runtime-asset-name "${PYTHON_RUNTIME_ASSET}" \ | |
| --python-runtime-archive "release-assets/${PYTHON_RUNTIME_ASSET}" \ | |
| --output "release-assets/${RELEASE_MANIFEST_ASSET}" | |
| - name: Generate release notes from changelog | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| python docs/skills/ops/tools/extractChangelogSection.py \ | |
| --version "${{ needs.build.outputs.package_version }}" \ | |
| --output release-assets/release-notes.md | |
| cat >> release-assets/release-notes.md <<'EOF' | |
| --- | |
| Download `Codaro.exe`, verify `Codaro.exe.sha256`, then run the launcher. The release also includes `release-manifest.json`, the exact `codaro` backend wheel, a managed Windows Python runtime archive, checksums, and SPDX SBOM assets. The manifest pins the wheel asset and sha256 from this GitHub Release. | |
| EOF | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| target_commitish: ${{ github.sha }} | |
| name: Codaro ${{ github.ref_name }} | |
| fail_on_unmatched_files: true | |
| body_path: release-assets/release-notes.md | |
| files: | | |
| release-assets/Codaro.exe | |
| release-assets/Codaro.exe.sha256 | |
| release-assets/Codaro.exe.spdx.json | |
| release-assets/python-runtime-win-x64.zip | |
| release-assets/python-runtime-win-x64.zip.sha256 | |
| release-assets/codaro-*.whl | |
| release-assets/codaro-*.whl.sha256 | |
| release-assets/release-manifest.json | |
| release-assets/codaro.spdx.json | |
| generate_release_notes: true |