Skip to content

chore(): Fix build in windows and test build/node in different OSes #2922

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 9 commits into from
Sep 2, 2021
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
83 changes: 68 additions & 15 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
paths-ignore:
- "**/*.md"
pull_request:
branches:
branches:
- "**"
release:
types:
Expand All @@ -29,10 +29,11 @@ jobs:
id: node_modules_cache
with:
path: ./node_modules
key: ${{ runner.os }}-14-9-node_modules-${{ hashFiles('yarn.lock') }}
key: ${{ runner.os }}-14-9-9-node_modules-${{ hashFiles('yarn.lock') }}
restore-keys: |
${{ runner.os }}-14-9-node_modules-
${{ runner.os }}-14-node_modules-
${{ runner.os }}-14-9-9-node_modules-
${{ runner.os }}-14-9-
${{ runner.os }}-14-
- name: Yarn offline cache
if: steps.node_modules_cache.outputs.cache-hit != 'true'
uses: actions/cache@v2
Expand All @@ -57,14 +58,16 @@ jobs:
retention-days: 1

test:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
needs: build
strategy:
matrix:
os: [ ubuntu-latest, macos-latest, windows-latest]
node: ["12", "14", "16"]
firebase: ["9"]
firebaseTools: ["9"]
fail-fast: false
name: Test firebase@${{ matrix.firebase }} on Node.js ${{ matrix.node }}
name: Test firebase@${{ matrix.firebase }} firebase-tools@${{ matrix.firebaseTools }} on ${{ matrix.os }} Node.js ${{ matrix.node }}
steps:
- name: Checkout
uses: actions/checkout@v2
Expand All @@ -78,10 +81,11 @@ jobs:
uses: actions/cache@v2
with:
path: ./node_modules
key: ${{ runner.os }}-${{ matrix.node }}-${{ matrix.firebase }}-node_modules-${{ hashFiles('yarn.lock') }}
key: ${{ runner.os }}-${{ matrix.node }}-${{ matrix.firebase }}-${{ matrix.firebaseTools }}-node_modules-${{ hashFiles('yarn.lock') }}
restore-keys: |
${{ runner.os }}-${{ matrix.node }}-${{ matrix.firebase }}-node_modules-
${{ runner.os }}-${{ matrix.node }}-node_modules-
${{ runner.os }}-${{ matrix.node }}-${{ matrix.firebase }}-${{ matrix.firebaseTools }}-node_modules-
${{ runner.os }}-${{ matrix.node }}-${{ matrix.firebase }}-
${{ runner.os }}-${{ matrix.node }}-
- name: Yarn offline cache
if: steps.node_modules_cache.outputs.cache-hit != 'true'
uses: actions/cache@v2
Expand All @@ -95,6 +99,7 @@ jobs:
yarn config set yarn-offline-mirror ~/.npm-packages-offline-cache
yarn install --frozen-lockfile --prefer-offline --ignore-engines
yarn add firebase@${{ matrix.firebase }} --prefer-offline --ignore-engines
yarn add firebase-tools@${{ matrix.firebaseTools }} --prefer-offline --ignore-engines
- name: Firebase emulator cache
uses: actions/cache@v2
with:
Expand All @@ -107,6 +112,52 @@ jobs:
mv angularfire-${{ github.run_id }} dist
yarn test:node

contribute:
runs-on: ${{ matrix.os }}
name: Contribute ${{ matrix.os }} on Node.js ${{ matrix.node }}
strategy:
matrix:
os: [ ubuntu-latest, macos-latest, windows-latest ]
node: ["12", "14", "16"]
exclude:
# we build with this combination, safely skip
- os: ubuntu-latest
node: 14
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v2-beta
with:
node-version: ${{ matrix.node }}
check-latest: true
- name: node_modules cache
uses: actions/cache@v2
id: node_modules_cache
with:
path: ./node_modules
key: ${{ runner.os }}-${{ matrix.node }}-9-9-node_modules-${{ hashFiles('yarn.lock') }}
restore-keys: |
${{ runner.os }}-${{ matrix.node }}-9-9-node_modules-
${{ runner.os }}-${{ matrix.node }}-9-
${{ runner.os }}-${{ matrix.node }}-
- name: Yarn offline cache
if: steps.node_modules_cache.outputs.cache-hit != 'true'
uses: actions/cache@v2
with:
path: ~/.npm-packages-offline-cache
key: yarn-offline-${{ hashFiles('**/yarn.lock') }}
restore-keys: yarn-offline
- name: Install deps
if: steps.node_modules_cache.outputs.cache-hit != 'true'
run: |
yarn config set yarn-offline-mirror ~/.npm-packages-offline-cache
yarn install --frozen-lockfile --prefer-offline --ignore-engines
- name: Build
id: yarn-pack-dir
run: yarn build

headless:
runs-on: ubuntu-latest
needs: build
Expand All @@ -129,10 +180,11 @@ jobs:
uses: actions/cache@v2
with:
path: ./node_modules
key: ${{ runner.os }}-14-${{ matrix.firebase }}-node_modules-${{ hashFiles('yarn.lock') }}
key: ${{ runner.os }}-14-${{ matrix.firebase }}-9-node_modules-${{ hashFiles('yarn.lock') }}
restore-keys: |
${{ runner.os }}-14-${{ matrix.firebase }}-node_modules-
${{ runner.os }}-14-node_modules-
${{ runner.os }}-14-${{ matrix.firebase }}-9-node_modules-
${{ runner.os }}-14-9-
${{ runner.os }}-14-
- name: Yarn offline cache
if: steps.node_modules_cache.outputs.cache-hit != 'true'
uses: actions/cache@v2
Expand Down Expand Up @@ -179,10 +231,11 @@ jobs:
# uses: actions/cache@v2
# with:
# path: ./node_modules
# key: ${{ runner.os }}-14-${{ matrix.firebase }}-node_modules-${{ hashFiles('yarn.lock') }}
# key: ${{ runner.os }}-14-${{ matrix.firebase }}-9-node_modules-${{ hashFiles('yarn.lock') }}
# restore-keys: |
# ${{ runner.os }}-14-${{ matrix.firebase }}-node_modules-
# ${{ runner.os }}-14-node_modules-
# ${{ runner.os }}-14-${{ matrix.firebase }}-9-node_modules-
# ${{ runner.os }}-14-${{ matrix.firebase }}-
# ${{ runner.os }}-14-
# - name: Yarn offline cache
# if: steps.node_modules_cache.outputs.cache-hit != 'true'
# uses: actions/cache@v2
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
"test:typings": "node ./tools/run-typings-test.js",
"test:build": "bash ./test/ng-build/build.sh",
"test:all": "npm run test:node && npm run test:chrome-headless && npm run test:typings && npm run test:build",
"build": "rimraf dist; ttsc -p tsconfig.build.json; node --trace-warnings ./tools/build.js",
"build:jasmine": "tsc -p tsconfig.jasmine.json; cp ./dist/packages-dist/schematics/versions.json ./dist/out-tsc/jasmine/schematics",
"build": "rimraf dist && ttsc -p tsconfig.build.json && node --trace-warnings ./tools/build.js",
"build:jasmine": "tsc -p tsconfig.jasmine.json && cp ./dist/packages-dist/schematics/versions.json ./dist/out-tsc/jasmine/schematics",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 1"
},
"husky": {
Expand Down Expand Up @@ -93,6 +93,7 @@
"codelyzer": "^6.0.0",
"concurrently": "^2.2.0",
"conventional-changelog-cli": "^1.2.0",
"cross-spawn": "^7.0.3",
"file-loader": "^6.2.0",
"firebase-functions-test": "^0.2.2",
"globalthis": "^1.0.1",
Expand Down
9 changes: 5 additions & 4 deletions src/schematics/deploy/actions.jasmine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { JsonObject, logging } from '@angular-devkit/core';
import { BuilderContext, BuilderRun, ScheduleOptions, Target } from '@angular-devkit/architect';
import { BuildTarget, FirebaseDeployConfig, FirebaseTools, FSHost } from '../interfaces';
import deploy, { deployToFunction } from './actions';
import { join } from 'path';
import 'jasmine';

let context: BuilderContext;
Expand Down Expand Up @@ -169,8 +170,8 @@ describe('universal deployment', () => {
const packageArgs = spy.calls.argsFor(0);
const functionArgs = spy.calls.argsFor(1);

expect(packageArgs[0]).toBe('dist/package.json');
expect(functionArgs[0]).toBe('dist/index.js');
expect(packageArgs[0]).toBe(join('dist', 'package.json'));
expect(functionArgs[0]).toBe(join('dist', 'index.js'));
});

it('should rename the index.html file in the nested dist', async () => {
Expand All @@ -191,8 +192,8 @@ describe('universal deployment', () => {
const packageArgs = spy.calls.argsFor(0);

expect(packageArgs).toEqual([
'dist/dist/browser/index.html',
'dist/dist/browser/index.original.html'
join('dist', 'dist', 'browser', 'index.html'),
join('dist', 'dist', 'browser', 'index.original.html')
]);
});

Expand Down
4 changes: 3 additions & 1 deletion src/schematics/ng-add.jasmine.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Tree } from '@angular-devkit/schematics';
import { setupProject } from './ng-add';
import 'jasmine';
import { join } from '@angular-devkit/core';
import { join as pathJoin } from 'path';

const PROJECT_NAME = 'pie-ka-chu';
const PROJECT_ROOT = 'pirojok';
Expand Down Expand Up @@ -335,7 +337,7 @@ const projectAngularJson = `{
const universalFirebaseJson = {
hosting: [{
target: 'pie-ka-chu',
public: 'dist/dist/ikachu',
public: pathJoin('dist', 'dist', 'ikachu'),
ignore: [
'**/.*'
],
Expand Down
123 changes: 71 additions & 52 deletions tools/build.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { spawn } from 'child_process';
import { spawn } from 'cross-spawn';
import { copy, readFile, writeFile } from 'fs-extra';
import { prettySize } from 'pretty-size';
import { file as gzipSizeFile } from 'gzip-size';
Expand Down Expand Up @@ -44,7 +44,7 @@ function zoneWrapExports() {
});
const zoneWrapped = toBeExported.filter(([, , zoneWrap]) => zoneWrap);
const rawExport = toBeExported.filter(([, , zoneWrap]) => !zoneWrap);
await writeFile(`./src/${module}/${name}.ts`, `// DO NOT MODIFY, this file is autogenerated by tools/build.ts
await writeFile(join(process.cwd(), 'src', `${module}/${name}.ts`), `// DO NOT MODIFY, this file is autogenerated by tools/build.ts
${path.startsWith('firebase/') ? `export * from '${path}';\n` : ''}${
zoneWrapped.length > 0 ? `import { ɵzoneWrap } from '@angular/fire';
import {
Expand Down Expand Up @@ -109,13 +109,14 @@ ${zoneWrapped.map(([importName, exportName]) => `export const ${exportName} = ɵ
}

function webpackFirestoreProtos() {
// TODO fix on windows
return new Promise<void>((resolve, reject) => {
glob('./node_modules/@firebase/firestore/dist/src/protos/**/*.proto', {}, async (err, files) => {
if (err) { reject(err); }
const fileLoader = files.map(path =>
`require('file-loader?name=${path.replace('./node_modules/@firebase/firestore/dist/', '')}!${path.replace('./node_modules/', '../../')}');`
).join('\n');
await writeFile('./dist/packages-dist/firestore-protos.js', fileLoader);
await writeFile(dest('firestore-protos.js'), fileLoader);
resolve();
});
});
Expand All @@ -132,7 +133,7 @@ function proxyPolyfillCompat() {
};

return Promise.all(Object.keys(defaultObject).map(module =>
writeFile(`./src/${module}/base.ts`, `// DO NOT MODIFY, this file is autogenerated by tools/build.ts
writeFile(join(process.cwd(), 'src', `${module}/base.ts`), `// DO NOT MODIFY, this file is autogenerated by tools/build.ts
// Export a null object with the same keys as firebase/${module}, so Proxy can work with proxy-polyfill in Internet Explorer
export const proxyPolyfillCompat = {
${defaultObject[module].map(it => ` ${it}: null,`).join('\n')}
Expand Down Expand Up @@ -197,6 +198,7 @@ async function fixImportForLazyModules() {
const entries = Array.from(new Set(Object.values(packageJson).filter(v => typeof v === 'string' && v.endsWith('.js')))) as string[];
// TODO don't hardcode esm2015 here, perhaps we should scan all the entry directories
// e.g, if ng-packagr starts building other non-flattened entries we'll lose the dynamic import
// TODO fix in Windows
entries.push(`../${module.includes('/') ? '../' : ''}esm2015/${module}/public_api.js`);
await Promise.all(entries.map(async path => {
const source = (await readFile(dest(module, path))).toString();
Expand Down Expand Up @@ -233,55 +235,72 @@ function measureLibrary() {
}

async function buildDocs() {
// INVESTIGATE json to stdout rather than FS?
await Promise.all(MODULES.map(module => spawnPromise('npx', ['typedoc', `${module === 'core' ? './src' : `./src/${module}`}`, '--json', `./dist/typedocs/${module}.json`])));
const entries = await Promise.all(MODULES.map(async (module) => {
try {
// INVESTIGATE json to stdout rather than FS?
await Promise.all(
MODULES.map(module =>
spawnPromise('npx', ['typedoc',
`${module === 'core' ?
join(process.cwd(), 'src') :
join(process.cwd(), 'src', module)}`,
'--json',
join(process.cwd(), 'dist', 'typedocs', `${module}.json`)
])));
const entries = await Promise.all(MODULES.map(async (module) => {

const buffer = await readFile(`./dist/typedocs/${module}.json`);
const typedoc = JSON.parse(buffer.toString());
if (!typedoc.children) {
console.error('typedoc fail', module);
}
// TODO infer the entryPoint from the package.json
const entryPoint = typedoc.children.find((c: any) => c.name === '"public_api"');
const allChildren = [].concat(...typedoc.children.map(child =>
// TODO chop out the working directory and filename
child.children ? child.children.map(c => ({ ...c, path: dirname(child.originalName.split(process.cwd())[1]) })) : []
));
return (entryPoint.children || [])
.filter(c => c.name[0] !== 'ɵ' && c.name[0] !== '_' /* private */)
.map(child => ({ ...allChildren.find(c => child.target === c.id) }))
.reduce((acc, child) => ({ ...acc, [encodeURIComponent(child.name)]: child }), {});
}));
const root = await rootPackage;
const pipes = ['MonoTypeOperatorFunction', 'OperatorFunction', 'AuthPipe', 'UnaryFunction'];
const tocType = child => {
const decorators: string[] = child.decorators && child.decorators.map(d => d.name) || [];
if (decorators.includes('NgModule')) {
return 'NgModule';
} else if (child.kindString === 'Type alias') {
return 'Type alias';
} else if (child.kindString === 'Variable' && child.defaultValue && child.defaultValue.startsWith('new InjectionToken')) {
return 'InjectionToken';
} else if (child.type) {
return pipes.includes(child.type.name) ? 'Pipe' : child.type.name;
} else if (child.signatures && child.signatures[0] && child.signatures[0].type && pipes.includes(child.signatures[0].type.name)) {
return 'Pipe';
} else {
return child.kindString;
}
};
const tableOfContents = entries.reduce((acc, entry, index) =>
({
...acc, [MODULES[index]]: {
name: ENTRY_NAMES[index],
exports: Object.keys(entry).reduce((acc, key) => ({ ...acc, [key]: tocType(entry[key]) }), {})
}
}),
{}
);
const afdoc = entries.reduce((acc, entry, index) => ({ ...acc, [MODULES[index]]: entry }), { table_of_contents: tableOfContents });
return writeFile(`./api-${root.version}.json`, JSON.stringify(afdoc, null, 2));
const buffer = await readFile(join(process.cwd(), 'dist', 'typedocs', `${module}.json`));
const typedoc = JSON.parse(buffer.toString());
if (!typedoc.children) {
console.error('typedoc fail', module);
}
// TODO infer the entryPoint from the package.json
const entryPoint = typedoc.children.find((c: any) => c.name === '"public_api"');
const allChildren = [].concat(...typedoc.children.map(child =>
// TODO chop out the working directory and filename
child.children ?
child.children.map(c => {
return { ...c, path: dirname(child.originalName.split(process.cwd())[1]) };
}) :
[]
));
return (entryPoint.children || [])
.filter(c => c.name[0] !== 'ɵ' && c.name[0] !== '_' /* private */)
.map(child => ({ ...allChildren.find(c => child.target === c.id) }))
.reduce((acc, child) => ({ ...acc, [encodeURIComponent(child.name)]: child }), {});
}));
const root = await rootPackage;
const pipes = ['MonoTypeOperatorFunction', 'OperatorFunction', 'AuthPipe', 'UnaryFunction'];
const tocType = child => {
const decorators: string[] = child.decorators && child.decorators.map(d => d.name) || [];
if (decorators.includes('NgModule')) {
return 'NgModule';
} else if (child.kindString === 'Type alias') {
return 'Type alias';
} else if (child.kindString === 'Variable' && child.defaultValue && child.defaultValue.startsWith('new InjectionToken')) {
return 'InjectionToken';
} else if (child.type) {
return pipes.includes(child.type.name) ? 'Pipe' : child.type.name;
} else if (child.signatures && child.signatures[0] && child.signatures[0].type && pipes.includes(child.signatures[0].type.name)) {
return 'Pipe';
} else {
return child.kindString;
}
};
const tableOfContents = entries.reduce((acc, entry, index) =>
({
...acc, [MODULES[index]]: {
name: ENTRY_NAMES[index],
exports: Object.keys(entry).reduce((acc, key) => ({ ...acc, [key]: tocType(entry[key]) }), {})
}
}),
{}
);
const afdoc = entries.reduce((acc, entry, index) => ({ ...acc, [MODULES[index]]: entry }), { table_of_contents: tableOfContents });
return writeFile(join(process.cwd(), `api-${root.version}.json`), JSON.stringify(afdoc, null, 2));
} catch (e) {
console.warn(e);
return Promise.resolve();
}
}

Promise.all([
Expand Down
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4977,7 +4977,7 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5:
shebang-command "^1.2.0"
which "^1.2.9"

cross-spawn@^7.0.1:
cross-spawn@^7.0.1, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
Expand Down