feat: support os parameter (#13511)

This commit is contained in:
Yury Semikhatsky 2022-04-12 22:20:48 -07:00 committed by GitHub
parent 7a5b070e95
commit 9b8aceaa61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 19 additions and 7 deletions

View File

@ -40,6 +40,10 @@ const githubFactory: GridFactory = {
}; };
async function createWorkflow(inputs: GridAgentLaunchOptions): Promise<boolean> { async function createWorkflow(inputs: GridAgentLaunchOptions): Promise<boolean> {
if (!['windows', 'linux', 'macos'].includes(inputs.os)) {
log(`unsupported OS: ${inputs.os}`);
return false;
}
return new Promise(fulfill => { return new Promise(fulfill => {
log(`triggering workflow ${JSON.stringify(inputs)}`); log(`triggering workflow ${JSON.stringify(inputs)}`);
const req = https.request(`https://api.github.com/repos/${repoName}/actions/workflows/agent.yml/dispatches`, { const req = https.request(`https://api.github.com/repos/${repoName}/actions/workflows/agent.yml/dispatches`, {

View File

@ -23,10 +23,13 @@ import { HttpServer } from '../utils/httpServer';
import { assert, createGuid } from '../utils'; import { assert, createGuid } from '../utils';
import { getPlaywrightVersion } from '../common/userAgent'; import { getPlaywrightVersion } from '../common/userAgent';
const defaultOS = 'linux';
export type GridAgentLaunchOptions = { export type GridAgentLaunchOptions = {
agentId: string, agentId: string,
gridURL: string, gridURL: string,
playwrightVersion: string, playwrightVersion: string,
os: string,
}; };
export type GridFactory = { export type GridFactory = {
@ -54,6 +57,7 @@ const WSErrors = {
WORKER_SOCKET_ERROR: { code: 1011, reason: 'Grid worker socket error' }, WORKER_SOCKET_ERROR: { code: 1011, reason: 'Grid worker socket error' },
CLIENT_PLAYWRIGHT_VERSION_MISMATCH: { code: 1013, reason: 'Grid Playwright and grid client versions are different' }, CLIENT_PLAYWRIGHT_VERSION_MISMATCH: { code: 1013, reason: 'Grid Playwright and grid client versions are different' },
AGENT_PLAYWRIGHT_VERSION_MISMATCH: { code: 1013, reason: 'Grid Playwright and grid agent versions are different' }, AGENT_PLAYWRIGHT_VERSION_MISMATCH: { code: 1013, reason: 'Grid Playwright and grid agent versions are different' },
CLIENT_UNSUPPORTED_OS: { code: 1013, reason: 'Unsupported OS' },
GRID_SHUTDOWN: { code: 1000, reason: 'Grid was shutdown' }, GRID_SHUTDOWN: { code: 1000, reason: 'Grid was shutdown' },
AGENT_MANUALLY_STOPPED: { code: 1000, reason: 'Grid agent was manually stopped' }, AGENT_MANUALLY_STOPPED: { code: 1000, reason: 'Grid agent was manually stopped' },
}; };
@ -117,6 +121,7 @@ type AgentStatus = 'none' | 'created' | 'connected' | 'retiring';
class GridAgent extends EventEmitter { class GridAgent extends EventEmitter {
private _capacity: number; private _capacity: number;
readonly agentId = createGuid(); readonly agentId = createGuid();
readonly os: string;
private _ws: WebSocket | undefined; private _ws: WebSocket | undefined;
readonly _workers = new Map<string, GridWorker>(); readonly _workers = new Map<string, GridWorker>();
private _status: AgentStatus = 'none'; private _status: AgentStatus = 'none';
@ -126,8 +131,9 @@ class GridAgent extends EventEmitter {
private _log: debug.Debugger; private _log: debug.Debugger;
private _agentCreationTimeoutId: NodeJS.Timeout; private _agentCreationTimeoutId: NodeJS.Timeout;
constructor(capacity = Infinity, creationTimeout = 5 * 60000, retireTimeout = 30000) { constructor(os: string, capacity = Infinity, creationTimeout = 5 * 60000, retireTimeout = 30000) {
super(); super();
this.os = os;
this._capacity = capacity; this._capacity = capacity;
this._log = debug(`pw:grid:agent:${this.agentId}`); this._log = debug(`pw:grid:agent:${this.agentId}`);
this.setStatus('created'); this.setStatus('created');
@ -155,8 +161,8 @@ class GridAgent extends EventEmitter {
this._workersWaitingForAgentConnected.clear(); this._workersWaitingForAgentConnected.clear();
} }
canCreateWorker() { canCreateWorker(os: string) {
return this._workers.size < this._capacity; return this.os === os && this._workers.size < this._capacity;
} }
async createWorker(clientSocket: WebSocket, params: GridWorkerParams) { async createWorker(clientSocket: WebSocket, params: GridWorkerParams) {
@ -266,7 +272,8 @@ export class GridServer {
ws.close(WSErrors.CLIENT_PLAYWRIGHT_VERSION_MISMATCH.code, WSErrors.CLIENT_PLAYWRIGHT_VERSION_MISMATCH.reason); ws.close(WSErrors.CLIENT_PLAYWRIGHT_VERSION_MISMATCH.code, WSErrors.CLIENT_PLAYWRIGHT_VERSION_MISMATCH.reason);
return; return;
} }
const agent = [...this._agents.values()].find(w => w.canCreateWorker()) || this._createAgent()?.agent; const os = params.get('os') || defaultOS;
const agent = [...this._agents.values()].find(w => w.canCreateWorker(os)) || this._createAgent(os)?.agent;
if (!agent) { if (!agent) {
this._log(`failed to get agent`); this._log(`failed to get agent`);
ws.close(WSErrors.AGENT_CREATION_FAILED.code, WSErrors.AGENT_CREATION_FAILED.reason); ws.close(WSErrors.AGENT_CREATION_FAILED.code, WSErrors.AGENT_CREATION_FAILED.reason);
@ -314,12 +321,12 @@ export class GridServer {
} }
public async createAgent(): Promise<{ error: any }> { public async createAgent(): Promise<{ error: any }> {
const { initPromise } = this._createAgent(); const { initPromise } = this._createAgent(defaultOS);
return await initPromise; return await initPromise;
} }
private _createAgent(): { agent: GridAgent, initPromise: Promise<{ error: any }> } { private _createAgent(os: string): { agent: GridAgent, initPromise: Promise<{ error: any }> } {
const agent = new GridAgent(this._factory.capacity, this._factory.launchTimeout, this._factory.retireTimeout); const agent = new GridAgent(os, this._factory.capacity, this._factory.launchTimeout, this._factory.retireTimeout);
this._agents.set(agent.agentId, agent); this._agents.set(agent.agentId, agent);
agent.on('close', () => { agent.on('close', () => {
this._agents.delete(agent.agentId); this._agents.delete(agent.agentId);
@ -329,6 +336,7 @@ export class GridServer {
agentId: agent.agentId, agentId: agent.agentId,
gridURL: this.gridURL(), gridURL: this.gridURL(),
playwrightVersion: getPlaywrightVersion(), playwrightVersion: getPlaywrightVersion(),
os
})).then(() => { })).then(() => {
this._log('created'); this._log('created');
return { error: undefined }; return { error: undefined };