diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml new file mode 100644 index 0000000..4b80534 --- /dev/null +++ b/.github/workflows/package.yml @@ -0,0 +1,75 @@ +# Build two downloadable packages. This does not publish to PyPI. +# Uploading to PyPI needs a token or trusted publishing, which this +# repository does not configure. A v* tag attaches the same files to a +# GitHub Release. + +name: Package + +on: + pull_request: + push: + branches: [main] + tags: ["v*"] + +jobs: + package: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Build the Python package + run: | + python -m pip install build + python -m build + + - name: Pack the skills + run: python scripts/pack_skills.py + + - name: Stage the two packages + run: | + mkdir -p packages/python packages/skills + cp dist/*.whl dist/*.tar.gz packages/python/ + cp dist/pyouter-skills-*.zip packages/skills/ + test -n "$(ls packages/python)" + test -n "$(ls packages/skills)" + + - uses: actions/upload-artifact@v4 + with: + name: pyouter-python + path: packages/python/ + + - uses: actions/upload-artifact@v4 + with: + name: pyouter-skills + path: packages/skills/ + + release: + if: startsWith(github.ref, 'refs/tags/v') + needs: package + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/download-artifact@v4 + with: + pattern: pyouter-* + path: release + merge-multiple: true + + - name: Attach both packages to the GitHub Release + env: + GH_TOKEN: ${{ github.token }} + run: | + tag="${GITHUB_REF_NAME}" + if gh release view "$tag" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then + gh release upload "$tag" release/* --repo "$GITHUB_REPOSITORY" --clobber + else + gh release create "$tag" release/* \ + --repo "$GITHUB_REPOSITORY" \ + --title "$tag" \ + --notes "Python package and skills package. This release does not publish to PyPI." + fi diff --git a/scripts/pack_skills.py b/scripts/pack_skills.py new file mode 100644 index 0000000..b2ccc0d --- /dev/null +++ b/scripts/pack_skills.py @@ -0,0 +1,35 @@ +"""Pack skills/ into dist/pyouter-skills-.zip. + +The version is the one written in setup.py. The archive keeps the skills/ +prefix, so unpacking it at a repository root restores that directory. +""" + +import re +import zipfile +from pathlib import Path + + +def version(): + text = Path("setup.py").read_text(encoding="utf-8") + found = re.search(r'version\s*=\s*"([^"]+)"', text) + if not found: + raise SystemExit("setup.py has no version") + return found.group(1) + + +def main(): + root = Path("skills") + files = [path for path in sorted(root.rglob("*")) if path.is_file()] + if not files: + raise SystemExit("skills/ is empty") + out_dir = Path("dist") + out_dir.mkdir(exist_ok=True) + out = out_dir / f"pyouter-skills-{version()}.zip" + with zipfile.ZipFile(out, "w", compression=zipfile.ZIP_DEFLATED) as archive: + for path in files: + archive.write(path, path.as_posix()) + print(out) + + +if __name__ == "__main__": + main()