Skip to content

Commit 758fbbf

Browse files
shibeshduwcloud-sdk-jsmarikanerdeekshas8
authored
chore: Move public-api-check script to GH action (#5113)
* v1 * compile issues * Changes from lint:fix * internal deps * Changes from lint:fix * changes from linting + use check in workflow * Changes from lint:fix * add action yml and use inputs to make it callable * fix run => uses * move check up * test path * added getPackages dep * Changes from lint:fix * move check down * use esbuild instead of ncc * add inputs * build.yml input * trim array items * cleanup * add test * normalize * fix test? * Changes from lint:fix * test errorSpy * whoops * -_- * revert * consistency * add conditionals for esm * regex fix * update + lint spec * try * use accessSync * using cross-env * Changes from lint:fix * cleanup * Changes from lint:fix --------- Co-authored-by: cloud-sdk-js <[email protected]> Co-authored-by: Marika Marszalkowski <[email protected]> Co-authored-by: Deeksha Sinha <[email protected]> Co-authored-by: deekshas8 <[email protected]>
1 parent 745766e commit 758fbbf

File tree

24 files changed

+93061
-385
lines changed

24 files changed

+93061
-385
lines changed

.github/actions/changesets-fixed-version-bump/index.js

Lines changed: 220 additions & 220 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: 'Check public API'
2+
description: 'Checks whether the public API is correctly exported.'
3+
inputs:
4+
force_internal_exports:
5+
description: 'Whether to force that everything is exported through the internal API.'
6+
default: 'false'
7+
excluded_packages:
8+
description: 'Packages to exclude when checking the public API.'
9+
ignored_paths:
10+
description: 'Paths to ignore when checking the public API.'
11+
12+
runs:
13+
using: 'node20'
14+
main: 'index.js'

.github/actions/check-public-api/index.js

Lines changed: 92531 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/build.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,10 @@ jobs:
7373
name: Test Service Version Check
7474
- run: yarn check:dependencies
7575
name: Undeclared dependency Check
76-
- run: yarn check:public-api
76+
- uses: ./.github/actions/check-public-api
77+
with:
78+
force_internal_exports: 'true'
79+
excluded_packages: 'eslint-config, util, test-util'
7780
name: Check public api
7881
- run: yarn test:self
7982
name: Self tests for tools

scripts/check-public-api.spec.ts renamed to build-packages/check-public-api/check-public-api.spec.ts

Lines changed: 70 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,40 @@
11
import mock from 'mock-fs';
2-
import { createLogger } from '@sap-cloud-sdk/util';
2+
import path from 'path';
3+
import * as core from '@actions/core';
34
import {
45
checkBarrelRecursive,
56
checkIndexFileExists,
67
exportAllInBarrel,
78
parseBarrelFile,
89
parseIndexFile,
9-
parseTypeDefinitionFile,
10+
parseExportedObjectsInFile,
1011
regexExportedIndex,
1112
typeDescriptorPaths
12-
} from './check-public-api';
13+
} from './index';
1314

1415
describe('check-public-api', () => {
15-
afterEach(() => mock.restore());
16+
let errorSpy: any;
1617

17-
it('checkIndexFileExists fails if index file is not in root', () => {
18-
mock({
19-
root: {
20-
dir1: {
21-
'index.ts': ''
22-
}
23-
}
24-
});
25-
expect(() => checkIndexFileExists('root/index.ts')).toThrowError(
26-
'No index.ts file found in root.'
27-
);
18+
beforeEach(() => {
19+
errorSpy = jest.spyOn(core, 'error').mockImplementation();
20+
});
21+
afterEach(() => {
22+
errorSpy.mockRestore();
23+
mock.restore();
2824
});
2925

3026
describe('exportAllInBarrel', () => {
31-
afterEach(() => mock.restore());
27+
it('checkIndexFileExists fails if index file is not in root', () => {
28+
mock({
29+
root: {
30+
dir1: {
31+
'index.ts': ''
32+
}
33+
}
34+
});
35+
checkIndexFileExists('root/index.ts');
36+
expect(errorSpy).toHaveBeenCalledWith('No index.ts file found in root.');
37+
});
3238

3339
it('fails if internal.ts is not present in root', async () => {
3440
mock({
@@ -39,14 +45,13 @@ describe('check-public-api', () => {
3945
}
4046
}
4147
});
42-
await expect(() =>
43-
exportAllInBarrel('src', 'internal.ts')
44-
).rejects.toThrowError("No 'internal.ts' file found in 'src'.");
48+
await exportAllInBarrel('src', 'internal.ts');
49+
expect(errorSpy).toHaveBeenCalledWith(
50+
"No 'internal.ts' file found in 'src'."
51+
);
4552
});
4653

4754
it('fails if a file is not exported in barrel file', async () => {
48-
const logger = createLogger('check-public-api');
49-
const errorSpy = jest.spyOn(logger, 'error');
5055
mock({
5156
dir1: {
5257
file1: '',
@@ -59,64 +64,64 @@ describe('check-public-api', () => {
5964
}
6065
});
6166

62-
await expect(() =>
63-
exportAllInBarrel('dir1', 'index.ts')
64-
).rejects.toThrowError("'index.ts' is not in sync.");
67+
await exportAllInBarrel('dir1', 'index.ts');
6568

6669
expect(errorSpy).toHaveBeenCalledWith(
67-
"'dir2' is not exported in 'dir1/index.ts'."
70+
`'dir2' is not exported in '${path.normalize('dir1/index.ts')}'.`
6871
);
72+
expect(errorSpy).toHaveBeenCalledWith("'index.ts' is not in sync.");
6973
});
70-
});
7174

72-
it('checkBarrelRecursive passes recursive check for barrel file exports', () => {
73-
mock({
74-
dir1: {
75-
file1: '',
76-
'index.ts': "export * from './file1'; export * from './dir2';",
77-
dir2: {
78-
file2: '',
79-
file3: '',
80-
'index.ts': "export * from './file2';export * from './file3';"
75+
it('checkBarrelRecursive passes recursive check for barrel file exports', async () => {
76+
mock({
77+
dir1: {
78+
file1: '',
79+
'index.ts': "export * from './file1'; export * from './dir2';",
80+
dir2: {
81+
file2: '',
82+
file3: '',
83+
'index.ts': "export * from './file2';export * from './file3';"
84+
}
8185
}
82-
}
86+
});
87+
await checkBarrelRecursive('dir1');
8388
});
84-
checkBarrelRecursive('dir1');
85-
});
8689

87-
it('typeDescriptorPaths finds the .d.ts files and excludes index.d.ts', () => {
88-
mock({
89-
dir1: {
90-
'file1.d.ts': '',
91-
'index.d.ts': '',
92-
dir2: {
93-
'file2.d.ts': '',
94-
'file3.d.ts': '',
95-
'index.d.ts': ''
90+
it('typeDescriptorPaths finds the .d.ts files and excludes index.d.ts', async () => {
91+
mock({
92+
dir1: {
93+
'file1.d.ts': '',
94+
'index.d.ts': '',
95+
dir2: {
96+
'file2.d.ts': '',
97+
'file3.d.ts': '',
98+
'index.d.ts': ''
99+
}
96100
}
97-
}
101+
});
102+
103+
expect(await typeDescriptorPaths('dir1')).toEqual([
104+
path.normalize('dir1/file1.d.ts'),
105+
path.normalize('dir1/dir2/file3.d.ts'),
106+
path.normalize('dir1/dir2/file2.d.ts')
107+
]);
98108
});
99-
expect(typeDescriptorPaths('dir1')).toEqual([
100-
'dir1/dir2/file2.d.ts',
101-
'dir1/dir2/file3.d.ts',
102-
'dir1/file1.d.ts'
103-
]);
104109
});
105110

106-
describe('parseTypeDefinitionFile', () => {
111+
describe('parseExportedObjectsInFile', () => {
107112
it('parses one .d.ts file', () => {
108-
const exportedType = parseTypeDefinitionFile(dummyTypeDefinition);
113+
const exportedType = parseExportedObjectsInFile(dummyTypeDefinition);
109114
expect(exportedType.map(e => e.name).sort()).toEqual([
110115
'CacheEntry',
111116
'IsolationStrategy',
112117
'MyType',
113-
'parseTypeDefinitionFile',
118+
'parseExportedObjectsInFile',
114119
'responseDataAccessor'
115120
]);
116121
});
117122

118123
it('parses one .d.ts file without content', () => {
119-
const exportedType = parseTypeDefinitionFile('some non matching');
124+
const exportedType = parseExportedObjectsInFile('some non matching');
120125
expect(exportedType).toEqual([]);
121126
});
122127
});
@@ -148,8 +153,6 @@ describe('check-public-api', () => {
148153
});
149154

150155
describe('parseIndexFile', () => {
151-
afterEach(() => mock.restore());
152-
153156
it('parses referenced star imports', async () => {
154157
mock({
155158
'index.ts': "export * from './common';export * from './subdir/ref';",
@@ -161,7 +164,7 @@ describe('check-public-api', () => {
161164
}
162165
});
163166

164-
await expect(parseIndexFile('index.ts')).resolves.toEqual([
167+
await expect(parseIndexFile('index.ts', true)).resolves.toEqual([
165168
'commonExport',
166169
'crossRefExport',
167170
'subdirRefExport'
@@ -176,7 +179,7 @@ describe('check-public-api', () => {
176179
'named.ts': "export type { namedExport } from './local'"
177180
});
178181

179-
const result = await parseIndexFile('index.ts');
182+
const result = await parseIndexFile('index.ts', true);
180183
expect(result).toEqual(['namedExport', 'commonExport']);
181184
});
182185

@@ -186,7 +189,9 @@ describe('check-public-api', () => {
186189
"export { ignoreme } from '@other/package';export { local } from './local';"
187190
});
188191

189-
await expect(parseIndexFile('index.ts')).resolves.toEqual(['local']);
192+
await expect(parseIndexFile('index.ts', true)).resolves.toEqual([
193+
'local'
194+
]);
190195
});
191196

192197
it('throws an error on internal re-exports', async () => {
@@ -195,7 +200,8 @@ describe('check-public-api', () => {
195200
"export { internal } from '@other/package/internal';export { local } from './local';"
196201
});
197202

198-
await expect(parseIndexFile('index.ts')).rejects.toThrowError(
203+
await parseIndexFile('index.ts', true);
204+
expect(errorSpy).toHaveBeenCalledWith(
199205
"Re-exporting internal modules is not allowed. 'internal' exported in 'index.ts'."
200206
);
201207
});
@@ -221,7 +227,7 @@ export declare enum IsolationStrategy {
221227
No_Isolation = "NoIsolation"
222228
}
223229
224-
export declare function parseTypeDefinitionFile(path: string): Promise<string[]>;
230+
export declare function parseExportedObjectsInFile(path: string): Promise<string[]>;
225231
export declare const responseDataAccessor: ResponseDataAccessor;
226232
227233
export declare type MyType = {value:string}

0 commit comments

Comments
 (0)