# Ignition Exchange resources Getting an Ignition project ready to publish on the Ignition Exchange means following Inductive Automation's naming and structure conventions — mainly so that when someone imports your resource into a project they already have, nothing of theirs gets overwritten. These files help you do that. | File | What it's for | |---|---| | **[`exchange_lint.py`](exchange_lint.py)** | Check your project against the conventions. Start here. | | **[`PUBLISHING.md`](PUBLISHING.md)** | Package and upload it, once it passes. | | [`Exchange+Resources+Style+Guide.md`](Exchange+Resources+Style+Guide.md) | The official guide, v1.1.0. Every rule traces back to it. | **The path: check your project → fix what it reports → follow `PUBLISHING.md`.** --- ## Checking your project ```bash python3 exchange_lint.py /path/to/YourProject ``` Nothing to install — Python 3.8+ and the standard library. Point it at any of these: - your project folder - a folder containing several projects (a gateway's `projects/` directory, an unpacked gateway backup, your repo) - a project export `.zip` - nothing, to scan the current directory There's no config file. It works out your resource name from the namespace your project already uses, and picks up tag exports and `.sql` dumps sitting alongside. --- ## Reading the report ``` Ignition Exchange Style Guide v1.1.0 — conformance report project: my-dashboard resource: MyDashboard Resource Structure FAIL E-NS-ROOT script-python/myutils: project library package 'myutils' is not under exchange//; importing would land scripts in the host project's namespace Perspective warn E-COMP-NAME views/Exchange/MyDashboard/Home: component 'headerRow' should be PascalCase summary: 1 failure(s), 12 warning(s); 21 of 38 rules exercised ``` Each finding gives you the file, the problem, and why it matters. ### FAIL — fix these before publishing Either the guide says *must*, or the rule protects your resource from damaging someone else's project on import: resource namespacing, session properties, Vision client tags, and the project-name character set. ### warn — your call These are naming conventions. The guide is explicit that they're *"encouraged, however these conventions are not required"*, and that consistency matters more than which convention you choose. Read them, decide, move on. Add `--strict` if you'd rather treat them as failures. ### "21 of 38 rules exercised" How many rules actually applied to your project. If you have no database, no tags and no named queries, those rules never ran — so a pass on a small project isn't mistaken for a pass on everything. **Exit codes:** `0` clean · `1` findings · `2` bad invocation. --- ## What gets checked 38 rules. Run `python3 exchange_lint.py --list-rules` for the full list with descriptions. | Area | What it looks at | |---|---| | **Resource structure** | Everything namespaced under `Exchange//` or `exchange//` — the guide's one hard *must*, and what keeps your import from overwriting the host project | | **Projects** | URL-friendly project name, human-friendly title, no version suffix | | **Perspective** | Naming of views, components, properties, pages and style classes; where style classes live; message-handler namespacing | | **Variable storage** | No session custom properties, no Vision client tags — both break a clean import | | **Code** | Tab indentation, camelCase functions and variables, PascalCase classes, docstrings, comment style, project-library layout | | **Loggers** | `exchange.resourceName.LoggerName` hierarchy | | **Database** | `ex_` table prefix, snake_case, `id` primary key, `_id` foreign keys | | **Tags · Vision · Named queries · WebDev · Translations** | Naming conventions for each | | **Upload readiness** | Description filled in, installation documentation present | ## What it can't check for you A clean report doesn't mean ready to publish. Still on you: - **What's written on screen.** It reads names and structure, never label text. A visible string like *"Acme Internal — do not distribute"* passes silently. Search your user-visible strings before you publish. - **That references still resolve.** It doesn't confirm an embedded view path, style class or script call points at something real. If you've just renamed things to fit the conventions, verify the project still works. - **That it runs.** Nothing is executed or rendered. Load it on a gateway and open the screens. - **Your export.** The documentation rule checks your working folder, not the zip you upload. See [`PUBLISHING.md`](PUBLISHING.md). --- ## Options | Flag | Effect | |---|---| | `--resource NAME` | Set your resource name, if the inferred one is wrong | | `--strict` | Treat every warning as a failure | | `--ignore E-PY-VAR,E-COMP-NAME` | Suppress specific rules | | `-v` | Show every occurrence instead of collapsing per rule | | `--max-per-rule N` | Change the collapse limit (default 8) | | `--json` | Machine-readable output, for CI | | `--tags` / `--sql` | Point at tag exports or SQL dumps explicitly | | `--list-rules` | Print the full rule table and exit | --- ## Findings that need context Three rules produce messages that can be confusing on first read. **`E-NS-ROOT` — why capital `Exchange/` sometimes and lowercase `exchange/` other times?** That's the guide's convention, not a typo. Views, windows, templates, named queries, reports, SFCs, transaction groups, alarm pipelines and tags go under `Exchange/`. Style classes, the project library, WebDev sources and images go under `exchange/`. Using the wrong root is a `FAIL`; using the right root with the wrong capitalisation is just a warning (`E-NS-CASE`). **`E-STYLE-HIER` may flag a class you're sharing deliberately.** It decides where a style class belongs by finding which views reference it — but it only sees class names written as plain text. If you build one in a binding, like `'exchange/my-resource/priority/' + level.lower()`, it can't see that usage and may report a shared class as used by only one view. If that's your situation, the warning is safe to ignore. **`E-PAGE-ROOT` isn't in the guide.** It's an added caution: mapping a page to `/` means your resource takes over the root URL of whatever project it's imported into. Worth knowing before you decide — the trade-off is that a resource with no `/` page can't be launched from the gateway's Perspective project list, only from its full page URL.