Skip to content

Commit

Permalink
Build frontend on install (#161)
Browse files Browse the repository at this point in the history
* Add npm build step to pyproject.toml

* Simplify github workflow

* Apparently build is not installed by default

* Try installing from wheels

* Try just sdist builds?

* Fix typo

* Try custom script

* Retry

* Build the wheel again as well

* Workflows wtf
  • Loading branch information
jelmervdl committed Sep 3, 2024
1 parent 4e8c7b4 commit 28507d6
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 123 deletions.
108 changes: 23 additions & 85 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,35 @@ on:
- published

jobs:
build_frontend:
name: Build frontend Javascript code
build:
name: Build source distribution
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- uses: actions/setup-python@v3

- uses: actions/setup-node@v3
with:
node-version: 18
node-version: 22

- name: Build frontend
working-directory: frontend
run: npm ci && npm run build
- name: Install build
run: python -m pip install build

- name: Set version number
if: startsWith(github.ref, 'refs/tags/v')
run: echo "VERSION = \"${GITHUB_REF_NAME:1}\"" > opuscleaner/__about__.py

- name: Build
run: python -m build

- uses: actions/upload-artifact@v3
with:
name: frontend
path: frontend/dist/
name: build-output
path: dist/opuscleaner-*.*

run_tests:
needs: [build_frontend]
needs: [build]
name: Run tests
runs-on: ubuntu-latest
steps:
Expand All @@ -38,95 +45,26 @@ jobs:

- uses: actions/download-artifact@v3
with:
name: frontend
path: frontend/dist
name: build-output
path: dist

- name: Install
run: python3 -m pip install .
run: python3 -m pip install dist/opuscleaner-*.whl

- name: Run runtime unittest
run: python3 -m unittest discover -s test

- name: Run filters unittest
run: python3 -m unittest discover -s opuscleaner/filters

build_sdist:
needs: [build_frontend]
name: Build source distribution
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- uses: actions/setup-python@v3

- uses: actions/download-artifact@v3
with:
name: frontend
path: frontend/dist

- name: Set version number
if: startsWith(github.ref, 'refs/tags/v')
run: echo "VERSION = \"${GITHUB_REF_NAME:1}\"" > opuscleaner/__about__.py

- name: Build sdist
run: pipx run build --sdist

- uses: actions/upload-artifact@v3
with:
name: sdist
path: dist/opuscleaner-*.tar.gz

build_wheels:
needs: [build_frontend]
name: Build wheels
runs-on: ubuntu-latest
# name: Build wheels on ${{ matrix.os }}
# runs-on: ${{ matrix.os }}
# strategy:
# matrix:
# os: [ubuntu-latest, windows-2019, macos-13]

steps:
- uses: actions/checkout@v3

- uses: actions/setup-python@v3

- uses: actions/download-artifact@v3
with:
name: frontend
path: frontend/dist

- name: Set version number
if: startsWith(github.ref, 'refs/tags/v')
run: echo "VERSION = \"${GITHUB_REF_NAME:1}\"" > opuscleaner/__about__.py

- name: Build wheels
run: python -m pip wheel -w wheelhouse .

# - name: Install cibuildwheel
# run: python -m pip install cibuildwheel==2.12.0

# - name: Build wheels
# run: python -m cibuildwheel --output-dir wheelhouse

- uses: actions/upload-artifact@v3
with:
name: wheels
path: ./wheelhouse/opuscleaner-*.whl

upload_pypi:
needs: [build_wheels, build_sdist]
needs: [build]
runs-on: ubuntu-latest
if: github.event_name == 'release' && github.event.action == 'published'
steps:
- uses: actions/download-artifact@v3
with:
name: wheels
path: dist

- uses: actions/download-artifact@v3
with:
name: sdist
name: build-output
path: dist

- uses: pypa/gh-action-pypi-publish@v1.5.0
Expand Down
10 changes: 3 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ If you just want to use OpusCleaner for cleaning, you can install it from PyPI,

```sh
pip3 install opuscleaner
opuscleaner-server serve
opuscleaner-server
```

Then you can go to http://127.0.0.1:8000/ to show the interface.
Expand Down Expand Up @@ -56,12 +56,9 @@ If you want to use another path, you can use the `DATA_PATH` environment variabl


### Installation for development
```sh
cd frontend
npm clean-install
npm run build
cd ..
For building from source (i.e. git, not anything downloaded from Pypi) you'll need to have node + npm installed.

```sh
python3 -m venv .env
bash --init-file .env/bin/activate
pip install -e .
Expand Down Expand Up @@ -105,4 +102,3 @@ To push a new release to Pypi from Github, tag a commit with a `vX.Y.Z` version
# Acknowledgements

This project has received funding from the European Union’s Horizon Europe research and innovation programme under grant agreement No 101070350 and from UK Research and Innovation (UKRI) under the UK government’s Horizon Europe funding guarantee [grant number 10052546]

51 changes: 20 additions & 31 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,17 @@ readme = "README.md"
requires-python = ">=3.9"
license = "MIT"
keywords = []
authors = [
{ name = "Jelmer van der Linde", email = "jelmer@ikhoefgeen.nl" },
]
authors = [{ name = "Jelmer van der Linde", email = "jelmer@ikhoefgeen.nl" }]
classifiers = [
"Development Status :: 4 - Beta",
"Programming Language :: Python",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
]
dynamic = [
"version",
"dependencies",
"optional-dependencies"
"Development Status :: 4 - Beta",
"Programming Language :: Python",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
]
dynamic = ["version", "dependencies", "optional-dependencies"]

[project.scripts]
opuscleaner-server = "opuscleaner.server:main"
Expand All @@ -44,10 +38,8 @@ Source = "https://github.com/hplt-project/opuscleaner"
path = "opuscleaner/__about__.py"

[tool.hatch.envs.default]
dependencies = [
"pytest",
"pytest-cov",
]
dependencies = ["pytest", "pytest-cov"]

[tool.hatch.envs.default.scripts]
cov = "pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=opuscleaner --cov=tests {args}"
no-cov = "cov --no-cov {args}"
Expand All @@ -56,13 +48,16 @@ no-cov = "cov --no-cov {args}"
python = ["39", "310", "311"]

[tool.hatch.build]
include = [
"/opuscleaner",
]
include = ["/opuscleaner"]

[tool.hatch.build.force-include]
[tool.hatch.build.targets.sdist.force-include]
"frontend/dist" = "/opuscleaner/frontend"

[tool.hatch.build.targets.sdist.hooks.custom]
path = "utils/frontend_build_hook.py"
working_dir = "frontend"
artifacts = ["frontend/dist"]

[tool.hatch.metadata.hooks.requirements_txt]
files = ["requirements.txt"]

Expand All @@ -72,13 +67,7 @@ all = ["requirements-all.txt"]
[tool.coverage.run]
branch = true
parallel = true
omit = [
"opuscleaner/__about__.py",
]
omit = ["opuscleaner/__about__.py"]

[tool.coverage.report]
exclude_lines = [
"no cov",
"if __name__ == .__main__.:",
"if TYPE_CHECKING:",
]
exclude_lines = ["no cov", "if __name__ == .__main__.:", "if TYPE_CHECKING:"]
32 changes: 32 additions & 0 deletions utils/frontend_build_hook.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import subprocess
import os
from typing import Any
import logging

from hatchling.builders.hooks.plugin.interface import BuildHookInterface


logger = logging.getLogger(__name__)


class NpmBuildHook(BuildHookInterface):
@property
def working_dir(self):
return self.config.get("working_dir", ".")

def initialize(self, version: str, build_data: dict[str, Any]) -> None:
# if we can't build because we don't have the build dir, skip
if not os.path.exists(self.working_dir):
logger.info(f"Skipping npm build because {self.working_dir=} does not exist")
return
# if we don't need to build because we have all the artifacts, skip
if all(os.path.exists(artifact) for artifact in self.config.get("artifacts", [])):
logger.info(f"Skipping npm build because all artifacts exist")
return
subprocess.check_output(
"npm install && npm run build",
shell=True,
cwd=self.working_dir)

def clean(self, versions: list[str]) -> None:
subprocess.check_output("npm run clean", shell=True, cwd=self.working_dir)

0 comments on commit 28507d6

Please sign in to comment.