Skip to content
Merged
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
6 changes: 6 additions & 0 deletions validate-pages/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Base URL of the Port API. Use https://api.us.getport.io for the US region.
PORT_API_URL=https://api.getport.io

# JSON array of organizations to validate. Each entry requires CLIENT_ID and
# CLIENT_SECRET; NAME is optional and only used to label the output.
ORGANIZATIONS=[{"NAME":"my-org","CLIENT_ID":"your_client_id_here","CLIENT_SECRET":"your_client_secret_here"}]
4 changes: 4 additions & 0 deletions validate-pages/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.env
node_modules
output
**/.DS_Store
81 changes: 81 additions & 0 deletions validate-pages/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Validate Pages Script

This script iterates over one or more Port organizations, lists every page in each organization, and validates them via the Port API. Any page that fails validation is printed along with its validation errors.

The script will:
1. Authenticate against each organization using its Port API credentials
2. List all pages in the organization (in compact form)
3. Validate each page via the Port API
4. Print any page that is invalid, together with its validation errors

It can output results in two ways:
- **Console** (`npm start`) — prints invalid pages to the terminal
- **HTML report** (`npm run report`) — generates a styled report at `output/index.html`

## Prerequisites

- Node.js (v16 or higher)
- npm
- Port API credentials (Client ID and Client Secret) for each organization you want to check

## Installation

1. Clone/Download this repository
2. Run `cd validate-pages`
3. Run `npm install` to install the dependencies
4. Copy `.env.example` to `.env` and fill in the values:

```bash
cp .env.example .env
```

## Configuration

The script is configured entirely through environment variables (loaded from `.env`):

| Variable | Required | Description |
| --------------- | -------- | ------------------------------------------------------------------------------------------------------- |
| `ORGANIZATIONS` | Yes | JSON array of organizations to validate. Each entry needs `CLIENT_ID` and `CLIENT_SECRET`; `NAME` is optional. |
| `PORT_API_URL` | No | Base URL of the Port API. Defaults to `https://api.getport.io`. Use `https://api.us.getport.io` for the US region. |

Example `ORGANIZATIONS` value (single line in `.env`):

```json
[{ "NAME": "my-org", "CLIENT_ID": "your_client_id_here", "CLIENT_SECRET": "your_client_secret_here" }]
```

## Running the Script

### Console output

Run the script with the following command:

```bash
npm start
```

For each organization the script prints the organization name and the number of pages found, then lists any invalid pages:

```
[my-org] 42 pages
INVALID some-broken-page: [{"message":"..."}]
```

If no invalid pages are found for an organization, only the summary line is printed.

### HTML report

To generate a shareable HTML report instead, run:

```bash
npm run report
```

This creates `output/index.html` with:
- Summary statistics (organizations, total pages, invalid pages, pages that failed to validate)
- A per-organization section listing each invalid page with its identifier, title, widget type/title, path, and validation error
- A "Failed to validate" table per organization for pages whose validation request errored (e.g. HTTP 500), so they can be checked manually

Open the file in any browser to view it. The `output/` directory is git-ignored.

Note: each run overwrites `output/index.html`, so only the last run's output is saved. Copy or rename the file if you want to keep a previous report.
94 changes: 94 additions & 0 deletions validate-pages/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/**
* Script: Validate Port Pages
*
* This script iterates over one or more Port organizations, lists every page in
* each organization, and validates them via the Port API. Any page that fails
* validation is printed along with its validation errors.
*
* Required environment variables (see .env.example):
* - ORGANIZATIONS: A JSON array of organizations to validate. Each entry must
* contain CLIENT_ID and CLIENT_SECRET, and may optionally contain NAME.
*
* Optional environment variables:
* - PORT_API_URL: Base URL of the Port API (defaults to https://api.getport.io).
*
* To generate an HTML report instead of console output, run `npm run report`.
*/

require("dotenv").config();

const { KeyError, getApiUrl, parseOrgs, collectFindings } = require("./portClient");

async function main() {
const apiUrl = getApiUrl();
const orgs = parseOrgs();

const results = [];
for (const org of orgs) {
results.push(await collectFindings(apiUrl, org));
}

printSummary(results);
}

/**
* Prints a consolidated summary of invalid pages across all organizations,
* grouped by organization, after all validation has finished. Pages that could
* not be validated (e.g. the validate request errored) are listed separately at
* the end so they can be manually checked in their organization.
*
* @param {Array<{name: string, totalPages: number, findings: Array<{identifier: string, errors: any[]}>, failedPages?: Array<{identifier: string, title?: string, reason: string}>}>} results
*/
function printSummary(results) {
const totalInvalid = results.reduce(
(sum, org) => sum + org.findings.length,
0
);
const totalFailed = results.reduce(
(sum, org) => sum + (org.failedPages ? org.failedPages.length : 0),
0
);

console.log("\n==================== SUMMARY ====================");

for (const org of results) {
console.log(`\n[${org.name}] ${org.findings.length} invalid / ${org.totalPages} pages`);

if (org.findings.length === 0) {
console.log(" All pages are valid");
} else {
for (const finding of org.findings) {
console.log(
` INVALID ${finding.identifier}: ${JSON.stringify(finding.errors)}`
);
}
}
}

console.log(
`\nTotal: ${totalInvalid} invalid page(s) across ${results.length} organization(s)`
);

if (totalFailed > 0) {
console.log("\n---- Failed pages to check (validation errored) ----");
for (const org of results) {
if (!org.failedPages || org.failedPages.length === 0) continue;
console.log(`\n[${org.name}]`);
for (const failed of org.failedPages) {
console.log(` FAILED ${failed.identifier}: ${failed.reason}`);
}
}
console.log(
`\nTotal: ${totalFailed} page(s) failed to validate across ${results.length} organization(s)`
);
}
}

main().catch((error) => {
if (error instanceof KeyError) {
console.error(`Missing env/config key: ${error.message}`);
} else {
console.error(error.message);
}
process.exit(1);
});
Loading