diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1bd6771..de4c00f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,36 +1,8 @@ name: CI on: - push: - branches: [main] pull_request: jobs: test: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - python-version: ["3.10", "3.11", "3.12"] - - steps: - - uses: actions/checkout@v4 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - # PySide6 needs a few native libs to load headlessly (offscreen Qt). - - name: Install Qt runtime libraries - run: sudo apt-get update && sudo apt-get install -y libegl1 libgl1 - - - name: Install package - run: pip install -e '.[dev,ui]' - - # The suite is fully offline. No proprietary res/ or captures/ are present - # in CI, so the hardware/resource-dependent tests skip automatically. - - name: Run tests - env: - QT_QPA_PLATFORM: offscreen - run: python -m pytest -q + uses: ./.github/workflows/tests.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..353d2c7 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,84 @@ +name: Release + +on: + push: + branches: [main] + tags: ['v*'] + +permissions: + contents: read + +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: false + +jobs: + test: + uses: ./.github/workflows/tests.yml + + build: + needs: test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Build sdist + wheel + run: | + pip install build + python -m build + + - name: Generate changelog notes + run: | + pip install git-cliff + if [ "${GITHUB_REF_TYPE}" = "tag" ]; then + git-cliff --current -o NOTES.md + else + git-cliff --unreleased -o NOTES.md + fi + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + name: dist + path: | + dist/* + NOTES.md + + release: + needs: build + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/download-artifact@v4 + with: + name: dist + + - name: Publish stable release (tag) + if: github.ref_type == 'tag' + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 + with: + tag_name: ${{ github.ref_name }} + name: ${{ github.ref_name }} + body_path: NOTES.md + prerelease: false + files: dist/* + + - name: Publish rolling 'latest' (main) + if: github.ref_type == 'branch' + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 + with: + tag_name: latest + name: "latest (nightly build of the trunk)" + body_path: NOTES.md + prerelease: true + make_latest: false + target_commitish: ${{ github.sha }} + files: dist/* diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..78059ca --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,37 @@ +name: Tests + +on: + workflow_call: + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.10", "3.11", "3.12"] + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + # PySide6 needs a few native libs to load headlessly (offscreen Qt). + - name: Install Qt runtime libraries + run: sudo apt-get update && sudo apt-get install -y libegl1 libgl1 + + - name: Install package + run: pip install -e '.[dev,ui]' + + # The suite is fully offline. No proprietary res/ or captures/ are present + # in CI, so the hardware/resource-dependent tests skip automatically. + - name: Run tests + env: + QT_QPA_PLATFORM: offscreen + run: python -m pytest -q diff --git a/.gitignore b/.gitignore index f4e72dc..c7ba27a 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,6 @@ htmlcov/ # Regenerated by the opencode CLI opencode.json + +# Internal design/plan docs (Spanish, local only — never in the public repo) +/docs/superpowers/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2a62a63..a2e712c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -43,3 +43,24 @@ USB vendor interface. By contributing you agree that your contributions are licensed under the project's [MIT License](LICENSE). + +## Releases + +The project uses Trunk-Based Development. The version is derived from git with +setuptools-scm; it is never edited by hand. + +- **Every push to `main`** triggers `release.yml`: it runs the tests, builds the + sdist+wheel, and overwrites the rolling `latest` pre-release with notes + generated from the commits. +- **Cutting a stable release:** from an up-to-date `main`, + + ```bash + git tag v0.2.0 + git push origin v0.2.0 + ``` + + The pipeline creates the permanent `0.2.0` Release with the sdist+wheel and the + changelog for the range since the previous tag. + +The changelog comes from commit messages (`cliff.toml`); there is no `CHANGELOG.md` +tracked in the repo. diff --git a/README.md b/README.md index b51cb24..b229cca 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,24 @@ not: Linux. - A POD Go connected over USB - For the UI: a Qt-capable desktop (PySide6 is installed via the `ui` extra) +## Download + +Prebuilt tarballs are attached to each GitHub Release: + +- **Latest (nightly build of the trunk):** the rolling `latest` pre-release always + tracks the freshest commit on `main`. +- **Stable:** numbered releases (`X.Y.Z`) cut from the trunk. + +Grab `openpodgo-.tar.gz` from +[Releases](https://github.com/agarat/openpodgo/releases) and install it: + +```bash +python3 -m venv .venv && . .venv/bin/activate +pip install "openpodgo-.tar.gz[ui]" # includes the UI +``` + +For USB access without sudo, see "USB access without sudo" below. + ## Install ```bash diff --git a/cliff.toml b/cliff.toml new file mode 100644 index 0000000..dfa2119 --- /dev/null +++ b/cliff.toml @@ -0,0 +1,33 @@ +# git-cliff config for openpodgo's release notes. +# Groups commits by the scope prefix used in this repo (catalog:, openpodgo:, docs:, ci:, ...). +[changelog] +header = "" +# NOTE: inside this TOML triple-quoted body, a \n is already a literal newline by the +# time Tera parses the template, so split(pat="\n") below splits on real newlines. +# Do not "escape" it to \\n — that would break the first-line truncation. +body = """ +{% for group, commits in commits | group_by(attribute="group") %} +### {{ group }} +{% for commit in commits %} +- {{ commit.message | split(pat="\n") | first | trim }}{% endfor %} +{% endfor %} +""" +trim = true + +[git] +conventional_commits = false +split_commits = false +commit_parsers = [ + { message = "^catalog", group = "Catálogo" }, + { message = "^openpodgo", group = "Core" }, + { message = "^ui", group = "UI" }, + { message = "^build", group = "Build" }, + { message = "^ci", group = "CI" }, + { message = "^docs", group = "Documentación" }, + { message = "^test", group = "Tests" }, + { message = "^fix", group = "Fixes" }, + { message = ".*", group = "Otros" }, +] +filter_commits = false +tag_pattern = "v[0-9]*" +sort_commits = "newest" diff --git a/pyproject.toml b/pyproject.toml index 275ea57..d44584b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openpodgo" -version = "0.1.0" +dynamic = ["version"] description = "Open-source editor for the Line 6 POD Go on Linux (a POD Go Edit clone)" readme = "README.md" requires-python = ">=3.10" @@ -34,7 +34,7 @@ dev = ["pytest>=7"] openpodgo = "openpodgo.app:main" [build-system] -requires = ["setuptools>=61"] +requires = ["setuptools>=61", "setuptools-scm>=8"] build-backend = "setuptools.build_meta" [tool.setuptools.packages.find] @@ -43,3 +43,9 @@ where = ["src"] [tool.pytest.ini_options] pythonpath = ["src"] testpaths = ["tests"] + +[tool.setuptools_scm] +# Versión derivada de los tags git (vX.Y.Z). Sin tag => versión .devN+g. +version_scheme = "guess-next-dev" +local_scheme = "node-and-date" +fallback_version = "0.0.0"