Skip to content

Commit

Permalink
Add CI script to check package paths (#6321)
Browse files Browse the repository at this point in the history
  • Loading branch information
hsubox76 committed Jun 2, 2022
1 parent 2cd1cc7 commit d4b52b6
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 4 deletions.
7 changes: 7 additions & 0 deletions .changeset/old-lamps-nail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@firebase/auth': patch
'@firebase/firestore': patch
'@firebase/installations-compat': patch
---

Fix incorrect paths in package.json
27 changes: 27 additions & 0 deletions .github/workflows/check-pkg-paths.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Test Package Paths

on: pull_request

jobs:
test:
name: Test Package Paths
runs-on: ubuntu-latest

steps:
- name: Checkout Repo
uses: actions/checkout@master
with:
# This makes Actions fetch all Git history so run-changed script can diff properly.
fetch-depth: 0
- name: Set up Node (14)
uses: actions/setup-node@v2
with:
node-version: 14.x
- name: Yarn install
run: yarn
- name: Yarn build
run: yarn build
- name: Swap in public typings
run: yarn release:prepare
- name: Check paths
run: yarn ts-node scripts/ci-test/check-paths.ts
2 changes: 1 addition & 1 deletion packages/auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"react-native": "dist/rn/index.js",
"browser": "dist/esm2017/index.js",
"module": "dist/esm2017/index.js",
"cordova": "dist/cordova/index.esm5.js",
"cordova": "dist/cordova/index.js",
"webworker": "dist/index.webworker.esm5.js",
"esm5": "dist/esm5/index.js",
"exports": {
Expand Down
6 changes: 3 additions & 3 deletions packages/firestore/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@
"require": "./dist/lite/index.node.cjs.js",
"import": "./dist/lite/index.node.mjs"
},
"react-native": "./dist/lite/index.rn.esm2017.js",
"esm5": "./dist/lite/index.browser.esm5.js",
"default": "./dist/lite/index.browser.esm2017.js"
"react-native": "./dist/index.rn.js",
"esm5": "./dist/index.esm5.js",
"default": "./dist/index.esm2017.js"
},
"./package.json": "./package.json"
},
Expand Down
148 changes: 148 additions & 0 deletions scripts/ci-test/check-paths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/**
* @license
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import glob from 'glob';
import { existsSync } from 'fs';
import { resolve } from 'path';
import { projectRoot as root } from '../utils';

/**
* Top level fields in package.json that may point to entry point and
* typings files.
*/
const TOP_LEVEL_FIELDS = [
'main',
'browser',
'module',
'typings',
'react-native',
'cordova',
'esm5',
'webworker',
'main-esm'
];

interface Result {
packageName: string;
found: boolean;
filePath: string;
fieldPath: string;
}
const results: Result[] = [];

/**
* Get paths to packages. Only check the ones we actually
* publish (packages/*).
*/
function getPaths(): Promise<string[]> {
return new Promise((resolve, reject) => {
glob('packages/*', (err, paths) => {
if (err) reject(err);
resolve(paths);
});
});
}

/**
* Recursively check `exports` field in package.json.
*/
function checkExports(
pkgName: string,
pkgRoot: string,
path: string = '',
exports: Record<string, any>
) {
for (const key in exports) {
if (typeof exports[key] === 'string') {
const filePath = resolve(pkgRoot, exports[key]);
const result = {
packageName: pkgName,
found: false,
filePath,
fieldPath: `exports${path}[${key}]`
};
if (existsSync(filePath)) {
result.found = true;
}
results.push(result);
} else {
checkExports(
pkgName,
pkgRoot,
path ? `${path}[${key}]` : `[${key}]`,
exports[key]
);
}
}
}

async function main() {
const paths = await getPaths();

for (const path of paths) {
const pkgRoot = `${root}/${path}`;
if (existsSync(`${pkgRoot}/package.json`)) {
const pkg = require(`${pkgRoot}/package.json`);

/**
* Check top level fields.
*/
for (const field of TOP_LEVEL_FIELDS) {
if (pkg[field]) {
const filePath = resolve(pkgRoot, pkg[field]);
const result = {
packageName: pkg.name,
found: false,
filePath,
fieldPath: field
};
if (existsSync(filePath)) {
result.found = true;
}
results.push(result);
}
}
/**
* Check all levels of exports field.
*/
if (pkg.exports) {
checkExports(pkg.name, pkgRoot, '', pkg.exports);
}
}
}

let missingPaths: boolean = false;

for (const result of results) {
if (!result.found) {
missingPaths = true;
console.log(
`${result.packageName}: Field "${result.fieldPath}" ` +
`points to ${result.filePath} which is not found.`
);
}
}

/**
* Fail CI if any missing paths found.
*/
if (missingPaths) {
process.exit(1);
}
}

main();

0 comments on commit d4b52b6

Please sign in to comment.