Files
BAT/exchangeResources/PUBLISHING.md
2026-09-15 13:06:45 -05:00

203 lines
8.8 KiB
Markdown

# Publishing a resource to the Ignition Exchange
How to take a conforming Ignition project and get it onto the Exchange: what file
format to upload, how to produce and verify it, and what to put in every field of
the upload form.
Companion to [`exchange_lint.py`](exchange_lint.py), which tests whether a project
follows the conventions, and to the
[Exchange Resources Style Guide](Exchange+Resources+Style+Guide.md), which is the
source for everything here.
---
## 1. What you upload
A **project export `.zip`** — the file Ignition produces from Designer's
File → Export, not a gateway backup.
| File | Upload as | Notes |
|---|---|---|
| `<resource>.zip` | Package file | The project export. The main artifact. |
| `README.md` (or PDF) | Package file | Separate upload — see the warning below. |
| Tag export `.json` | Package file | Only if the resource needs tags/UDTs. |
| Database dump `.sql` | Package file | Only if it needs a schema or seed data. |
| Screenshots `.png` | Images & Screenshots | Optional, strongly encouraged. |
> **Never upload a gateway backup (`.gwbk`).** It contains your entire gateway —
> datasource credentials, journal profiles, tags, every other project. It is the
> wrong artifact and it leaks configuration into a public resource.
The Exchange accepts multiple package files, up to 10 MB each.
### The README will probably not be inside the zip
Ignition's project export serialises **recognised project resources** — each is a
directory containing a `resource.json`. A loose `README.md` at the project root
is not a project resource, so the export is expected to drop it.
This is reasoning from how the export works, not a verified observation. **Unzip
your export and check** before uploading. Either way the guide tells you to
upload documentation separately:
> **Note:** If you already have detailed documentation for your resource please
> note it here and include the documentation file in the Package File upload.
Note also that `exchange_lint.py`'s `E-UP-DOCS` rule checks the working
directory, not the shipped package. A passing lint does not prove the zip
carries your docs.
---
## 2. Before you package
### Run the conformance checker
```bash
python3 exchangeResources/exchange_lint.py <project-dir>
```
Zero failures is the bar. Warnings are naming conventions the guide calls
"encouraged, not required" — review them and decide, rather than silencing them
by contorting the project. Document any you deliberately keep.
### Work the guide's own checklist
The guide names four pre-upload checks. Three are often N/A for a
journal- or tag-only resource; the first never is:
1. **Check the project export.** Import the exported zip into a brand-new
project and confirm it works. Then import it into a project that *already has
content* — that is the case the namespacing rules exist for, and the only way
to prove nothing collides.
2. **Include the tags.** If the resource needs tags or UDTs, export them and
verify the export covers everything the project binds to.
3. **Don't forget database backups.** If it expects tables or seed data, include
the dump and name the vendor (MySQL / MSSQL / PostgreSQL) in the description
*and* in the install instructions.
4. **Take notes while you test.** Those notes become the Custom Installation
Instructions field. Readers range from beginner to intermediate.
### Strip anything internal
Search the project for company names, project codenames, internal hostnames,
ticket numbers and placeholder text — in **user-visible strings**, not just
comments. The linter does not check content, only names and structure.
```bash
grep -rniE "yourcompany|internal|localhost|todo|fixme|demo only" <project-dir>
```
Check rendered label text too; a `props.text` value is easy to miss in JSON.
---
## 3. Produce the export
**Designer** — File → Export, select the project.
**Gateway web UI** — Config → Projects → *project* → Export.
Both produce the same zip. If your repo stores projects as unpacked files
(gateway-as-files), there is no zip in the repo — you must generate one.
---
## 4. Verify the export
```bash
unzip -l <resource>.zip # inventory
unzip -o <resource>.zip -d /tmp/verify-export # extract
```
Check:
- **File count** matches the project on disk (minus anything the export legitimately drops).
- **Every view, style class and script module** you expect is present.
- **`README.md` presence** — confirm, do not assume.
- **No stray files**: `.resources/` (gateway-owned cache), `__pycache__`, editor backups.
- **No credentials** anywhere in the archive.
Then do the real test: import it into a populated project and click through.
---
## 5. Fill in the upload form
Fields in the order the Exchange presents them.
### Overview
| Field | What to put |
|---|---|
| **Visibility** | `Public` unless it is genuinely private. |
| **Title** | Short, Title Case, says what it does. Usually matches the project title. |
| **Tagline** | One sentence. Must **not** repeat the title. |
| **Description** | What it does, how it is meant to be used, who benefits, relevant industries. |
| **Resource Type** | Closest match from the dropdown, plus a skill level reflecting install/use complexity. |
| **Background Image** | Optional colour/design for the resource card. |
| **Category** | **Up to 3.** Chosen from: Alarming, Analytics, Connectivity, Dashboard, Diagnostics, Edge Computing, Enterprise, HMI, IIOT/MQTT, MES, Maintenance, Mapping/GIS, Mobile, Monitoring, Reporting, SCADA, Scripting, Security, Simulation, Trending/Charting, Utility. |
| **Contact the Developer** | Optional. Your address is never shown; you receive the question plus the asker's address. |
| **Tags** | **Up to 10** search keywords. |
| **Images & Screenshots** | Optional but highly encouraged — shows what the title and description cannot. |
### Package
| Field | What to put |
|---|---|
| **Version** | `1.0.0` for a first release; later versions auto-increment. **Do not** put the version in the project name. |
| **Ignition Platform** | The **minimum** version required. The guide: *"If unsure, select the Ignition platform version in which the package was developed with."* Do not claim a floor you have not tested. |
| **Release Tagline** | Short summary of this version's changes. Required even for the first release. |
| **Release Notes** | Fuller explanation of what changed and how it affects users. |
| **Required Modules** | Any Inductive Automation / Cirrus Link / Sepasoft modules needed. |
| **Maker Edition** | Tick if it runs on Maker. Unavailable if you require modules Maker does not support. |
| **Other Requirements** | External or custom prerequisites, one per line. Blank if none. |
| **Package Files** | The zip, plus docs / tags / SQL as applicable. |
| **Custom Installation Instructions** | Step-by-step setup. Assume a beginner. If you shipped separate documentation, say so here and include the file. |
The Exchange **auto-generates a readme** from your Description and Custom
Installation Instructions, so write both properly.
### Verifying your minimum-version claim
Spin up a throwaway gateway at the version you intend to declare and load the
project into it. Use a **copy** of the project files — an older gateway rewrites
`resource.json` metadata and leaves root-owned `.resources/` artifacts behind.
A clean load proves resources parse. It does **not** prove screens render: a
component property added in a later version fails at render time, not load time.
Open the client and look.
---
## 6. Worked example — Alarm Analysis Dashboard
| Field | Value |
|---|---|
| Title | Alarm Analysis Dashboard |
| Tagline | ISA-18.2 alarm performance metrics straight from the alarm journal |
| Resource Type | Perspective View — Intermediate |
| Category | Alarming, Analytics, Dashboard |
| Tags | alarms, ISA-18.2, alarm journal, MTTA, MTTR, bad actors, alarm rate, KPI, dashboard, perspective |
| Version | 1.0.0 |
| Ignition Platform | 8.1.20 |
| Required Modules | Perspective |
| Maker Edition | Compatible |
| Other Requirements | An alarm journal profile with data |
| Package Files | `alarm-analysis.zip`, `README.md` |
Needs no tag export and no database dump — it reads the journal through
`system.alarm.queryJournal` / `queryStatus` with no journal name, datasource or
tag dependency. That portability is what the guide's structure rules produce.
---
## 7. After publishing
- **Updates** are new package versions on the same resource, not new resources.
Keep the namespace stable so users' imports upgrade in place.
- **Never rename the namespace folders** between versions — that turns an upgrade
into a duplicate set of resources in every user's project.
- Re-run `exchange_lint.py` before every release.
- Non-English resources: the guide encourages shipping a language dropdown with
English alongside, to widen access.