Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Install dependencies
run: |
python -m pip install --upgrade pip
Expand All @@ -26,9 +26,9 @@ jobs:
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
steps:
- name: Check out repository code
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
Expand All @@ -45,3 +45,22 @@ jobs:
fail_ci_if_error: true
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

portability:
name: Core CLI / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-14]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install core CLI without native extras
run: pip install .[test]
- name: Exercise core commands
run: |
ntk --help
python -m pytest -q
51 changes: 50 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ If you already have `python` and `pip`, install with the following command:
pip install next-theme-kit
```

The core CLI is pure Python and installs on macOS (including Apple Silicon), Linux, and native Windows.
Install optional features only when a project needs them:

```bash
pip install 'next-theme-kit[sass]' # legacy libsass compilation
pip install 'next-theme-kit[capture]' # screenshot capture; then: playwright install chromium
```

#### Mac OSX Requirements
See how to install `python` and `pip` with [HomeBrew](https://docs.brew.sh/Homebrew-and-Python#python-3x). Once you have completed this step you can install using the `pip` instructions above.

Expand Down Expand Up @@ -50,6 +58,8 @@ Store authentication uses [OAuth 2.0](https://auth0.com/intro-to-iam/what-is-oau

`ntk` reads its connection settings from two places: command flags (`--apikey`, `--store`, `--theme_id`) and the `config.yml` file in your theme directory. You do not need to create `config.yml` by hand — `ntk checkout` and `ntk init` write it for you, and after that commands run without flags:

Store values are normalized to an absolute HTTPS origin: `store.example.com` and `http://store.example.com` become `https://store.example.com`. Paths, credentials, query strings, fragments, and non-HTTP schemes are rejected.

```yaml
development:
apikey: <api key>
Expand Down Expand Up @@ -93,6 +103,8 @@ With the package installed, you can now use the commands inside your theme direc
| `ntk push` | Push current theme state to store |
| `ntk watch` | Watch for local changes and automatically push changes to store |
| `ntk sass` | Process sass to css, see [Sass Processing](#sass-processing) |
| `ntk validate` | Validate theme files locally or against the store |
| `ntk capture` | Capture deterministic desktop and mobile PNGs |

### Browse Store Themes

Expand Down Expand Up @@ -152,7 +164,7 @@ On success, `ntk init` logs the new theme ID and name, and persists the theme ID
To sync files between your local directory and the store, use `ntk push` to upload and `ntk pull` to download. Both upload or download the whole theme by default, and both accept file paths as positional arguments to limit the operation to specific files.

> [!NOTE]
> File paths are relative to the theme root. `ntk push` only uploads files inside the theme directories (`assets`, `checkout`, `configs`, `layouts`, `locales`, `partials`, `sass`, `templates`) with valid theme file extensions — a path outside of them is skipped silently, not reported as an error.
> File paths are relative to the theme root. `ntk push` only uploads files inside the theme directories (`assets`, `checkout`, `configs`, `layouts`, `locales`, `partials`, `sass`, `templates`) with valid theme file extensions. Explicit unsupported or missing paths are reported as rejected and make the command fail.

| Example | Command |
| ------- | ------- |
Expand All @@ -177,6 +189,43 @@ On start, `ntk watch` logs the store, theme ID, a preview-theme URL, and the dir
> [!NOTE]
> `ntk watch` only uploads files with valid theme extensions. It does not accept file arguments. To scope changes to specific files, run `ntk push` with file paths instead.

### Validate Before Upload

Run deterministic local checks for JSON syntax, template block balance, supported paths, and unsafe custom-product inheritance:

```bash
ntk validate templates/catalogue/product.subscription.html configs/settings.json
```

Add `--server` to submit locally valid text files to the platform's template validator without saving them:

```bash
ntk validate --server templates/catalogue/product.subscription.html
```

Local validation does not claim to prove a complete runtime render. Server validation requires the store, API key, and theme ID from flags or `config.yml`.

### Capture Reproducible Screenshots

With the `capture` extra and Chromium installed, capture real rendered PNGs at the fixed 1440px desktop and 390px mobile widths:

```bash
ntk capture --url="/?preview_theme=<theme-id>&skip_cache=1" \
--output=qa-output --viewports=desktop,mobile --json --no-progress
```

Capture waits for network idle, web fonts, lazy-loaded content, and images before writing full-page PNGs. It is suitable for local use and CI; it never substitutes DOM metrics for visual evidence.

### Automation Output

Every finite command accepts `--json`, `--quiet`, and `--no-progress`. `--json` writes exactly one versioned result object to stdout; logs stay on stderr, and progress is automatically disabled for JSON and non-interactive output. Push/pull/validation results are reported per file. Authentication, network, validation, rejection, and partial-transfer failures return a non-zero exit status.

The JSON envelope is stable within schema version `1`:

```json
{"schema_version":"1","command":"push","ok":true,"count":1,"results":[{"path":"templates/index.html","status":"uploaded"}]}
```

### Sass Processing

Theme kit includes support for Sass processing via [Python Libsass](https://sass.github.io/libsass-python/). Sass processing includes support for variables, imports, nesting, mixins, inheritance, custom functions, and more.
Expand Down
26 changes: 21 additions & 5 deletions ntk/__main__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#!/usr/bin/env python
import logging
import sys

from requests.exceptions import HTTPError

from ntk.ntk_parser import Parser
from ntk.output import Output

logging.basicConfig(
format='%(asctime)s %(levelname)s %(message)s',
Expand All @@ -16,15 +18,29 @@ def main():
parser = Parser().create_parser()
args = parser.parse_args()
try:
args.func(args)
result = args.func(args)
if isinstance(result, dict) and not result.get('ok', True):
sys.exit(1)
except AttributeError:
print('Use ntk -h or --help to see available commands')
except (TypeError, HTTPError) as e:
# print new line for support error on process progress bar
print()
logging.exception(e, exc_info=False)
except (TypeError, HTTPError, RuntimeError) as e:
if getattr(args, 'json', False) is True:
output = Output()
output.configure(args)
output.error(getattr(args, 'command', 'ntk'), e, error_type=e.__class__.__name__)
else:
logging.exception(e, exc_info=False)
sys.exit(1)
except KeyboardInterrupt:
pass
except Exception as e:
if getattr(args, 'json', False) is True:
output = Output()
output.configure(args)
output.error(getattr(args, 'command', 'ntk'), e, error_type=e.__class__.__name__)
else:
logging.exception(e)
sys.exit(1)


if __name__ == '__main__':
Expand Down
Loading
Loading