Adjust CI checks (#7851)

This commit is contained in:
Jaco 2022-07-09 18:59:17 +02:00 committed by GitHub
parent fcd0367a10
commit d8b98782d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 186 additions and 116 deletions

10
jest-ci.config.cjs Normal file
View File

@ -0,0 +1,10 @@
// Copyright 2017-2022 @polkadot/apps authors & contributors
// SPDX-License-Identifier: Apache-2.0
const config = require('@polkadot/dev/config/jest.cjs');
module.exports = {
...config,
moduleNameMapper: {},
testTimeout: 2 * 60 * 1000
};

View File

@ -15,6 +15,7 @@
"url": "https://github.com/polkadot-js/apps.git"
},
"sideEffects": false,
"type": "module",
"version": "0.116.2-93-x",
"workspaces": [
"packages/*"
@ -36,8 +37,8 @@
"build:release:www": "yarn polkadot-ci-ghact-build && yarn build:release:ghpages && yarn build:release:ipfs",
"build:robohash": "node scripts/robohash.cjs",
"build:www": "rm -rf packages/apps/build && mkdir -p packages/apps/build && yarn run build:i18n && cd packages/apps && yarn webpack --config webpack.config.cjs",
"ci:chainEndpoints": "NODE_OPTIONS=--max_old_space_size=8192 polkadot-dev-run-test --runInBand packages/apps-config/src/ci/chainEndpoints",
"ci:chainTypes": "NODE_OPTIONS=--max_old_space_size=8192 polkadot-dev-run-test --runInBand packages/apps-config/src/ci/chainTypes",
"ci:chainEndpoints": "NODE_OPTIONS=--experimental-vm-modules polkadot-dev-run-test --config ./jest-ci.config.cjs --runInBand --detectOpenHandles packages/apps-config/src/ci/chainEndpoints",
"ci:chainTypes": "NODE_OPTIONS=--experimental-vm-modules polkadot-dev-run-test --config ./jest-ci.config.cjs --runInBand --detectOpenHandles packages/apps-config/src/ci/chainTypes",
"clean": "polkadot-dev-clean-build",
"clean:electronBuild": "cd packages/apps-electron && polkadot-dev-clean-build",
"clean:electronRelease": "cd packages/apps-electron && rm -rf release",

View File

@ -1,9 +1,13 @@
// Copyright 2017-2022 @polkadot/apps-config authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { checkEndpoints } from './util';
import { checkEndpoints } from './runner';
describe('--SLOW--: check configured chain endpoints', (): void => {
beforeAll((): void => {
jest.setTimeout(2 * 60 * 1000);
});
checkEndpoints('./.github/chain-endpoints.md', [
'No DNS entry for',
'Timeout connecting to',

View File

@ -1,9 +1,13 @@
// Copyright 2017-2022 @polkadot/apps-config authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { checkEndpoints } from './util';
import { checkEndpoints } from './runner';
describe.skip('--SLOW--: check configured chain types', (): void => {
beforeAll((): void => {
jest.setTimeout(2 * 60 * 1000);
});
checkEndpoints('./.github/chain-types.md', [
'Unknown types'
]);

View File

@ -0,0 +1,88 @@
// Copyright 2017-2022 @polkadot/apps-config authors & contributors
// SPDX-License-Identifier: Apache-2.0
import fs from 'fs';
import { ApiPromise, WsProvider } from '@polkadot/api';
import { assert, isError } from '@polkadot/util';
import { typesBundle, typesChain } from '../api';
import { fetchJson } from './fetch';
interface DnsResponse {
Answer?: { name: string }[];
Question: { name: string }[];
}
const TICK = '`';
export function checkEndpoint (issueFile: string, failures: string[]): (name: string, ws: string) => Promise<boolean> {
return async (name: string, ws: string): Promise<boolean> => {
const [,, hostWithPort] = ws.split('/');
const [host] = hostWithPort.split(':');
const json = await fetchJson<DnsResponse>(`https://dns.google/resolve?name=${host}`);
let provider: WsProvider | null = null;
let api: ApiPromise | null = null;
let timerId: NodeJS.Timeout | null = null;
try {
assert(json.Answer, `No DNS entry for ${host}`);
provider = new WsProvider(ws, false);
api = new ApiPromise({
provider,
throwOnConnect: true,
throwOnUnknown: false,
typesBundle,
typesChain
});
setTimeout((): void => {
provider &&
provider
.connect()
.catch(() => undefined);
}, 1000);
await Promise.race([
// eslint-disable-next-line promise/param-names
new Promise((_, reject): void => {
timerId = setTimeout((): void => {
timerId = null;
reject(new Error(`Timeout connecting to ${ws}`));
}, 30_000);
}),
api.isReadyOrError
.then((a) => a.rpc.chain.getBlock())
.then((b) => console.log(b.toHuman()))
]);
} catch (error) {
if (isError(error) && failures.some((f) => (error as Error).message.includes(f))) {
process.env.CI_LOG && fs.appendFileSync(issueFile, `\n${TICK}${name} @ ${ws} ${error.message}${TICK}\n`);
throw error;
}
console.error(JSON.stringify(error));
} finally {
if (timerId) {
clearTimeout(timerId);
}
if (provider) {
try {
if (api) {
await api.disconnect();
} else {
await provider.disconnect();
}
} catch {
// ignore
}
}
}
return Promise.resolve(true);
};
}

View File

@ -0,0 +1,38 @@
// Copyright 2017-2022 @polkadot/apps authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { fetch } from '@polkadot/x-fetch';
// a fetch with a 2s timeout
async function fetchWithTimeout (url: string, timeout = 2000): Promise<Response> {
const controller = new AbortController();
let isAborted = false;
const id = setTimeout((): void => {
console.log(`Timeout on ${url}`);
isAborted = true;
controller.abort();
}, timeout);
try {
const response = await fetch(url, { signal: controller.signal });
clearTimeout(id);
return response;
} catch (error) {
if (!isAborted) {
clearTimeout(id);
}
throw error;
}
}
export function fetchJson <T> (url: string, timeout = 2000): Promise<T> {
return fetchWithTimeout(url, timeout).then<T>((r) => r.json());
}
export function fetchText (url: string, timeout = 2000): Promise<string> {
return fetchWithTimeout(url, timeout).then((r) => r.text());
}

View File

@ -0,0 +1,37 @@
// Copyright 2017-2022 @polkadot/apps-config authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { isString } from '@polkadot/util';
import { createWsEndpoints } from '../endpoints';
import { checkEndpoint } from './check';
interface Endpoint {
name: string;
ws: string;
}
export function checkEndpoints (issueFile: string, failures: string[]): void {
const checker = checkEndpoint(issueFile, failures);
it.each(
createWsEndpoints()
.filter(({ isDisabled, isUnreachable, value }) =>
!isDisabled &&
!isUnreachable &&
value &&
isString(value) &&
!value.includes('127.0.0.1') &&
!value.startsWith('light://')
)
.map(({ text, value }): Partial<Endpoint> => ({
name: text as string,
ws: value
}))
.filter((v): v is Endpoint => !!v.ws)
)('%name @ %$ws', ({ name, ws }): Promise<void> => {
console.error(`>>> ${name} @ ${ws}`);
return checker(name, ws).then((r) => expect(r).toBe(true));
});
}

View File

@ -1,112 +0,0 @@
// Copyright 2017-2022 @polkadot/apps-config authors & contributors
// SPDX-License-Identifier: Apache-2.0
import fs from 'fs';
import { ApiPromise, WsProvider } from '@polkadot/api';
import { assert, isError, isString } from '@polkadot/util';
import { fetch } from '@polkadot/x-fetch';
import { typesBundle, typesChain } from '../api';
import { createWsEndpoints } from '../endpoints';
interface Endpoint {
name: string;
ws: string;
}
interface DnsResponse {
Answer?: { name: string }[];
Question: { name: string }[];
}
const TICK = '`';
export function checkEndpoints (issueFile: string, failures: string[]): void {
createWsEndpoints()
.filter(({ isDisabled, isUnreachable, value }) =>
!isDisabled &&
!isUnreachable &&
value &&
isString(value) &&
!value.includes('127.0.0.1') &&
!value.startsWith('light://')
)
.map(({ text, value }): Partial<Endpoint> => ({
name: text as string,
ws: value
}))
.filter((v): v is Endpoint => !!v.ws)
.forEach(({ name, ws }) =>
it(`${name} @ ${ws}`, async (): Promise<void> => {
console.error(`>>> ${name} @ ${ws}`);
const [,, hostWithPort] = ws.split('/');
const [host] = hostWithPort.split(':');
const response = await fetch(`https://dns.google/resolve?name=${host}`);
const json = await response.json() as DnsResponse;
let provider: WsProvider | null = null;
let api: ApiPromise | null = null;
let timerId: NodeJS.Timeout | null = null;
try {
assert(json.Answer, `No DNS entry for ${host}`);
provider = new WsProvider(ws, false);
api = new ApiPromise({
provider,
throwOnConnect: true,
throwOnUnknown: false,
typesBundle,
typesChain
});
setTimeout((): void => {
provider &&
provider
.connect()
.catch(() => undefined);
}, 1000);
await Promise.race([
// eslint-disable-next-line promise/param-names
new Promise((_, reject): void => {
timerId = setTimeout((): void => {
timerId = null;
reject(new Error(`Timeout connecting to ${ws}`));
}, 30_000);
}),
api.isReadyOrError
.then((a) => a.rpc.chain.getBlock())
.then((b) => console.log(b.toHuman()))
]);
} catch (error) {
if (isError(error) && failures.some((f) => (error as Error).message.includes(f))) {
process.env.CI_LOG && fs.appendFileSync(issueFile, `\n${TICK}${name} @ ${ws} ${error.message}${TICK}\n`);
throw error;
}
console.error(JSON.stringify(error));
} finally {
if (timerId) {
clearTimeout(timerId);
}
if (provider) {
try {
if (api) {
await api.disconnect();
} else {
await provider.disconnect();
}
} catch {
// ignore
}
}
}
})
);
}