-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add power-platform-connectors type to /new-repo #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
9066a4f
feat: add power-platform-connectors type to /new-repo
PBNZ 40459c7
fix(power-platform-connectors): address review — determinism + temp h…
PBNZ 7600ef8
fix(power-platform-connectors): address Gemini review — robustness + …
PBNZ f6e40fc
fix(power-platform-connectors): report the configured size limit, not…
PBNZ eb2db33
fix(power-platform-connectors): round-3 review — robustness + non-roo…
PBNZ fa6298c
fix(power-platform-connectors): round-4 review — valid oauth2 + no da…
PBNZ 94293cb
fix(power-platform-connectors): round-5 review — $ref responses + slu…
PBNZ 8b3b8de
fix(power-platform-connectors): harden generator + workflows from sel…
PBNZ 8f2d7d2
fix(power-platform-connectors): scope the unresolved-var scan to conn…
PBNZ 3c53aa8
fix(power-platform-connectors): address final-round review (1 HIGH + …
PBNZ File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| # ADR-0003: `power-platform-connectors` repo type | ||
|
|
||
| - **Status:** accepted | ||
| - **Date:** 2026-07-04 | ||
|
|
||
| ## Context | ||
|
|
||
| We needed a repo **type** that turns a Postman collection into OpenAPI definitions ready to import | ||
| as **Microsoft Power Platform custom connectors**. Verified hard constraints from Microsoft Learn | ||
| (*Create a custom connector from an OpenAPI definition*): the definition must be **OpenAPI 2.0 / | ||
| Swagger** ("OpenAPI 3.0 format is not supported") and **< 1 MB**, `.json` or `.yaml`, with a single | ||
| top security definition (client-credentials OAuth is rejected). | ||
|
|
||
| ## Decision | ||
|
|
||
| - **Converter (free, pinned in Docker):** `postman-to-openapi@3.0.1` outputs OpenAPI **3.0** only, | ||
| so we downconvert with `api-spec-converter@2.12.0` (`--from=openapi_3 --to=swagger_2`). Both are | ||
| unmaintained (2023 / 2021; the latter depends on the deprecated `request`) and do **not** run on | ||
| current Node — the image is pinned to **Node 18**. Do not bump without re-testing. APIMatic (paid, | ||
| direct Postman→2.0) is the documented escape hatch, not built. | ||
| - **The downconvert is lossy, so `generate.mjs` normalises the output to valid Swagger 2.0** — this | ||
| was proven empirically (a real public collection failed validation four different ways before the | ||
| fixups): (1) **pre-resolve collection `{{variables}}`** so `host`/`basePath`/`schemes` are real | ||
| instead of `%7B%7Bbaseurl%7D%7D`; (2) **derive `securityDefinitions` from the Postman `auth`** | ||
| block (p2o mis-maps apikey to an invalid `type:http` and drops the header name); (3) **backfill a | ||
| `description` on every response** (required in 2.0; p2o only sets it from the Postman `status`); | ||
| (4) **add missing path parameters and leading `/`** on path keys. The generator then | ||
| **self-validates** each output with `swagger-cli` and asserts **< 1 MB**, exiting non-zero on any | ||
| failure. | ||
| - **Split policy:** convert the whole collection to one definition; ship one file if it's < 1 MB; | ||
| otherwise split **per top-level folder** (each carrying the collection `variable`/`auth`); if a | ||
| single folder is still ≥ 1 MB after stripping example fields, **flag it** rather than ship an | ||
| un-importable file. | ||
| - **Self-containment / source:** the collection is **committed** (`source/collection.json`), so the | ||
| repo builds with just Docker — no Postman account. **Sync** fetches a **configurable `sourceUrl`**: | ||
| a public URL (GitHub raw / vendor site) is **account-free**; a Postman-platform-only collection | ||
| needs the maintainer's optional `POSTMAN_API_KEY` secret (never needed by cloners). Postman has no | ||
| reliable anonymous fetch for a collection you don't own (public JSON links are deprecated). | ||
| - **Change detection = scheduled workflow + hash:** `sync.yml` (daily cron + dispatch) canonicalises | ||
| the fetched collection, SHA-256s it, compares to `.postman/manifest.json`, and on a change updates | ||
| the snapshot, regenerates, **validates inline**, and opens a PR. Validation is inline because a PR | ||
| opened by the default `GITHUB_TOKEN` does not trigger `ci.yml`. This needs | ||
| `permissions: pull-requests: write` and the repo setting *Allow GitHub Actions to create and | ||
| approve pull requests*. | ||
| - **Tier: Core + Public, no Published** (like `docker-compose`) — "publishing" is manually importing | ||
| a definition into Power Platform; there is no registry step to automate. | ||
|
|
||
| ## Consequences | ||
|
|
||
| - The conversion is lossy — the pipeline validates and opens a **PR to review**; it never | ||
| auto-imports. Richer collections (saved example responses, one clear auth scheme) produce better | ||
| connectors. | ||
| - The toolchain is stale but pinned in Docker; if a future Node breaks it, the pin holds. | ||
| - Auto-sync is account-free for public-URL sources; Postman-platform-only collections need the | ||
| maintainer's optional key. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 4 additions & 0 deletions
4
...kit/skills/new-repo/templates/types/power-platform-connectors/core/.postman/manifest.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| { | ||
| "sourceUrl": "", | ||
| "sha256": "" | ||
| } |
14 changes: 14 additions & 0 deletions
14
plugins/repokit/skills/new-repo/templates/types/power-platform-connectors/core/Dockerfile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| # Pinned toolchain for generating Power Platform custom-connector definitions. | ||
| # | ||
| # Node is pinned to 18 on purpose: the converters are unmaintained | ||
| # (postman-to-openapi 2023, api-spec-converter 2021 — the latter depends on the | ||
| # deprecated `request` module) and do NOT run on current Node. Do not bump the | ||
| # Node line or the tool versions without re-testing the whole pipeline. | ||
| FROM node:18-bullseye-slim | ||
|
|
||
| # --ignore-scripts blocks install-time lifecycle scripts (defence-in-depth for this stale, | ||
| # transitive-heavy dependency tree). These three tools are pure JS and run fine without them. | ||
| RUN npm install -g --ignore-scripts postman-to-openapi@3.0.1 api-spec-converter@2.12.0 @apidevtools/swagger-cli@4.0.4 | ||
|
|
||
| WORKDIR /work | ||
| # The repo is mounted at /work at run time; run: node scripts/generate.mjs |
65 changes: 65 additions & 0 deletions
65
...ins/repokit/skills/new-repo/templates/types/power-platform-connectors/core/README.md.tmpl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| # {{name}} | ||
|
|
||
| {{description}} | ||
|
|
||
| OpenAPI **2.0** connector definitions for **Microsoft Power Platform** custom connectors, | ||
| generated from a Postman collection. Each definition is valid Swagger 2.0 and kept **under 1 MB** | ||
| (Power Platform's limits — 3.0 is not supported). The collection is **committed to this repo**, so | ||
| anyone can regenerate the connectors with just Docker — no Postman account needed. | ||
|
|
||
| ## How it works | ||
|
|
||
| ```mermaid | ||
| flowchart LR | ||
| Src["source/collection.json<br/>(committed Postman collection)"] --> Gen["generate.mjs, in Docker"] | ||
| Gen --> Q{"whole def under 1 MB?"} | ||
| Q -->|yes| One["one connectors/*.swagger.json"] | ||
| Q -->|no| Split["split per top-level folder"] | ||
| One --> Val["validate: Swagger 2.0 + under 1 MB"] | ||
| Split --> Val | ||
| Val --> Imp["import into Power Platform"] | ||
| ``` | ||
|
|
||
| ## Use it | ||
|
|
||
| 1. Export your Postman collection (v2.1) and save it as **`source/collection.json`**. | ||
| 2. Set `sourceUrl` in **`connectors.config.json`** — a public URL to the collection JSON (a GitHub | ||
| raw file or the vendor's site), or the Postman API endpoint if the collection lives only in | ||
| Postman. | ||
| 3. Generate the definitions (one Docker command — no local Node needed): | ||
|
|
||
| ```sh | ||
| docker build -t {{name}}-gen . | ||
| docker run --rm -v "${PWD}:/work" {{name}}-gen node scripts/generate.mjs | ||
| ``` | ||
|
|
||
| *(On Linux/macOS, add `--user "$(id -u):$(id -g)"` to the `docker run` so the generated files | ||
| aren't owned by root.)* | ||
|
|
||
| It writes `connectors/*.swagger.json` — **one file if the whole collection fits under 1 MB, | ||
| otherwise one per top-level folder**. Every file is validated as Swagger 2.0 and checked < 1 MB; | ||
| the run fails if any definition is invalid or oversize. | ||
| 4. In Power Platform (Power Automate / Power Apps / Logic Apps): **New custom connector → Import an | ||
| OpenAPI file** → pick a `connectors/*.swagger.json`. | ||
|
|
||
| ## Keeping it up to date | ||
|
|
||
| - **CI** (`.github/workflows/ci.yml`) rebuilds + regenerates + validates on every change to | ||
| `source/`, `scripts/`, the `Dockerfile`, or the config. | ||
| - **Auto-sync** (`.github/workflows/sync.yml`) runs daily: it fetches `sourceUrl`, and if the | ||
| upstream collection changed, it updates `source/collection.json`, regenerates, validates, and | ||
| opens a **PR** for you to review. Account-free when `sourceUrl` is a public URL. If the collection | ||
| lives only in Postman, add a `POSTMAN_API_KEY` repo secret (only the maintainer needs it — never | ||
| cloners), and enable *Settings → Actions → Allow GitHub Actions to create and approve pull requests*. | ||
|
|
||
| ## Heads-up — review before importing | ||
|
|
||
| The Postman → Swagger 2.0 conversion is **lossy** (it drops `oneOf/anyOf`, `nullable`, and derives | ||
| response schemas from saved example responses). The pipeline fixes the common breakages | ||
| (host/basePath, security definitions, response descriptions) and validates every output, but | ||
| **review the connector in the PR before importing**. Richer collections — with saved example | ||
| responses and a single clear auth scheme — produce better connectors. Power Platform also picks the | ||
| single top security definition and rejects OAuth client-credentials. | ||
|
|
||
| See [`AGENTS.md`](AGENTS.md) for the START-HERE map. Follows the | ||
| [RepoKit](https://github.com/PBNZ/repo-kit) standard. | ||
5 changes: 5 additions & 0 deletions
5
...kit/skills/new-repo/templates/types/power-platform-connectors/core/connectors.config.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| { | ||
| "sourceUrl": "<fill me: a public URL to the Postman collection JSON, e.g. a GitHub raw file; or the Postman API endpoint if it is Postman-only>", | ||
| "sizeLimitBytes": 1048576, | ||
| "output": "connectors" | ||
| } |
Empty file.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Running the Docker container as root locally can result in generated files in the workspace being owned by root, which prevents local developers from editing or deleting them without using
sudo. Passing--user "$(id -u):$(id -g)"ensures files are created with the correct host user ownership.