Skip to content

Commit

Permalink
chore(repo): eslint Wing CLI source code (winglang#4381)
Browse files Browse the repository at this point in the history
I was running into some bugs working on the CLI that took me a while to find because I had forgotten to `await` some promises (that eslint would have caught!) so this felt worth adding. The `eslint` config is copied from the `vscode-wing` package.

## Checklist

- [ ] Title matches [Winglang's style guide](https://www.winglang.io/contributing/start-here/pull_requests#how-are-pull-request-titles-formatted)
- [ ] Description explains motivation and solution
- [ ] Tests added (always)
- [ ] Docs updated (only required for features)
- [ ] Added `pr/e2e-full` label if this feature requires end-to-end testing

*By submitting this pull request, I confirm that my contribution is made under the terms of the [Wing Cloud Contribution License](https://github.com/winglang/wing/blob/main/CONTRIBUTION_LICENSE.md)*.
  • Loading branch information
Chriscbr authored Oct 4, 2023
1 parent d7ceee4 commit 0e8e85f
Show file tree
Hide file tree
Showing 30 changed files with 878 additions and 370 deletions.
134 changes: 134 additions & 0 deletions apps/wing/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
{
"env": {
"jest": true,
"node": true
},
"root": true,
"plugins": [
"@typescript-eslint",
"import",
"prettier"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module",
"project": "./tsconfig.json"
},
"extends": [
"plugin:import/typescript",
"prettier",
"plugin:prettier/recommended"
],
"settings": {
"import/parsers": {
"@typescript-eslint/parser": [
".ts",
".tsx"
]
},
"import/resolver": {
"node": {},
"typescript": {
"project": "./tsconfig.json",
"alwaysTryTypes": true
}
}
},
"ignorePatterns": [
"*.js",
"*.d.ts",
"node_modules/",
"*.generated.ts",
"coverage",
"!.projenrc.ts",
"!projenrc/**/*.ts"
],
"rules": {
"prettier/prettier": [
"error"
],
"@typescript-eslint/no-require-imports": [
"error"
],
"import/no-extraneous-dependencies": [
"error",
{
"devDependencies": [
"**/test/**",
"**/build-tools/**",
"src/**",
".projenrc.ts",
"projenrc/**/*.ts"
],
"optionalDependencies": false,
"peerDependencies": true
}
],
"import/no-unresolved": [
"error"
],
"import/order": [
"warn",
{
"groups": [
"builtin",
"external"
],
"alphabetize": {
"order": "asc",
"caseInsensitive": true
}
}
],
"no-duplicate-imports": [
"error"
],
"no-shadow": [
"off"
],
"@typescript-eslint/no-shadow": [
"error"
],
"key-spacing": [
"error"
],
"no-multiple-empty-lines": [
"error"
],
"@typescript-eslint/no-floating-promises": [
"error"
],
"no-return-await": [
"off"
],
"@typescript-eslint/return-await": [
"error"
],
"no-trailing-spaces": [
"error"
],
"dot-notation": [
"error"
],
"no-bitwise": [
"error"
],
"@typescript-eslint/member-ordering": [
"error",
{
"default": [
"public-static-field",
"public-static-method",
"protected-static-field",
"protected-static-method",
"private-static-field",
"private-static-method",
"field",
"constructor",
"method"
]
}
]
}
}
9 changes: 9 additions & 0 deletions apps/wing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
},
"scripts": {
"build": "tsc && pnpm copy-root-readme",
"eslint": "eslint --ext .ts src",
"compile": "tsc",
"copy-root-readme": "cp ../../README.md ./README.md && pnpm copy-root-assets",
"copy-root-assets": "cp ../../logo/demo.gif ./logo/demo.gif",
Expand Down Expand Up @@ -53,8 +54,16 @@
"@types/node-persist": "^3.1.4",
"@types/semver-utils": "^1.1.1",
"@types/uuid": "^8.3.4",
"@typescript-eslint/eslint-plugin": "^6.7.4",
"@typescript-eslint/parser": "^6.7.4",
"bump-pack": "workspace:^",
"esbuild": "^0.17.19",
"eslint": "^8.50.0",
"eslint-config-prettier": "^8.10.0",
"eslint-import-resolver-node": "^0.3.9",
"eslint-import-resolver-typescript": "^3.6.0",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-prettier": "^4.2.1",
"typescript": "^4.9.5",
"vitest": "^0.30.1"
},
Expand Down
34 changes: 16 additions & 18 deletions apps/wing/src/analytics/collect.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { Command } from "commander";
import { AnalyticEvent } from "./event";
import { OSCollector } from "./collectors/os-collector";
import { NodeCollector } from "./collectors/node-collector";
import { CLICollector } from "./collectors/cli-collector";
import { CICollector } from "./collectors/ci-collector";
import { AnalyticsStorage } from "./storage";
import { CLICollector } from "./collectors/cli-collector";
import { GitCollector } from "./collectors/git-collector";

import { NodeCollector } from "./collectors/node-collector";
import { OSCollector } from "./collectors/os-collector";
import { AnalyticEvent } from "./event";
import { AnalyticsStorage } from "./storage";

/**
* Collects analytics for a given command, stores it for later export
*
*
* @param cmd The commander command to collect analytics for
* @returns string the file path of the stored analytic
*/
Expand All @@ -23,25 +22,24 @@ export async function collectCommandAnalytics(cmd: Command): Promise<string | un
// If entrypoint to app is provided, we will give that to git collector to use for
// running queries against the git repo, otherwise we will use the current working directory
const gitCollector = new GitCollector({
appEntrypoint: cmd.args.length > 0 ? cmd.args[0] : '.'
appEntrypoint: cmd.args.length > 0 ? cmd.args[0] : ".",
});
const eventName = `cli_${cmd.opts().target ?? ''}_${cmd.name()}`;

const eventName = `cli_${cmd.opts().target ?? ""}_${cmd.name()}`;

let event: AnalyticEvent = {
event: eventName.replace(/[^a-zA-Z_]/g, ""),
properties: {
cli: await cliCollector.collect(),
os: await osCollector.collect(),
node: await nodeCollector.collect(),
ci: await ciCollector.collect(),
anonymous_repo_id: (await gitCollector.collect())?.anonymous_repo_id
}
}
const storage = new AnalyticsStorage({debug: process.env.DEBUG ? true : false});
anonymous_repo_id: (await gitCollector.collect())?.anonymous_repo_id,
},
};
const storage = new AnalyticsStorage({ debug: process.env.DEBUG ? true : false });

let analyticFilePath = storage.storeAnalyticEvent(event);

return analyticFilePath;
}

28 changes: 14 additions & 14 deletions apps/wing/src/analytics/collectors/ci-collector.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {describe, test, expect, beforeEach } from "vitest";
import { describe, test, expect, beforeEach } from "vitest";
import { CICollector } from "./ci-collector";

describe("ci collector tests", () => {
const originialEnvironment = process.env;

beforeEach(() => {
// Restore the environment back to where it was before any of the
// Restore the environment back to where it was before any of the
// tests manipulated it
process.env = { ...originialEnvironment }
process.env = { ...originialEnvironment };
});

test("should return undefined when no ci environment is detected", async () => {
Expand All @@ -20,7 +20,7 @@ describe("ci collector tests", () => {

// THEN
expect(ciData).toBeUndefined();
})
});

describe("should return correct CI environment name", () => {
let collector: CICollector;
Expand All @@ -36,63 +36,63 @@ describe("ci collector tests", () => {
process.env.GITHUB_ACTIONS = "1";

// THEN
expect(await collector.collect()).toEqual({name: "GITHUB_ACTIONS"})
expect(await collector.collect()).toEqual({ name: "GITHUB_ACTIONS" });
});

test("when in Gitlab ci", async () => {
// WHEN
process.env.GITLAB_CI = "1";

// THEN
expect(await collector.collect()).toEqual({name: "GITLAB_CI"})
expect(await collector.collect()).toEqual({ name: "GITLAB_CI" });
});

test("when in Jekins", async () => {
// WHEN
process.env.JENKINS_URL = "1";

// THEN
expect(await collector.collect()).toEqual({name: "JENKINS"})
expect(await collector.collect()).toEqual({ name: "JENKINS" });
});

test("when in Circleci", async () => {
// WHEN
process.env.CIRCLECI = "1";

// THEN
expect(await collector.collect()).toEqual({name: "CIRCLECI"})
expect(await collector.collect()).toEqual({ name: "CIRCLECI" });
});

test("when in Bitbucket", async () => {
// WHEN
process.env.BITBUCKET_BUILD_NUMBER = "1";

// THEN
expect(await collector.collect()).toEqual({name: "BITBUCKET"})
expect(await collector.collect()).toEqual({ name: "BITBUCKET" });
});

test("when in Azure Devops", async () => {
// WHEN
process.env.BUILD_BUILDID = "1";

// THEN
expect(await collector.collect()).toEqual({name: "AZURE_DEVOPS"})
expect(await collector.collect()).toEqual({ name: "AZURE_DEVOPS" });
});

test("when in Teamcity", async () => {
// WHEN
process.env.TEAMCITY_VERSION = "1";

// THEN
expect(await collector.collect()).toEqual({name: "TEAMCITY"})
expect(await collector.collect()).toEqual({ name: "TEAMCITY" });
});

test("when in AWS Codebuild", async () => {
// WHEN
process.env.CODEBUILD_BUILD_ID = "1";

// THEN
expect(await collector.collect()).toEqual({name: "CODEBUILD"})
expect(await collector.collect()).toEqual({ name: "CODEBUILD" });
});
})
});
});
});
8 changes: 4 additions & 4 deletions apps/wing/src/analytics/collectors/ci-collector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export interface CIData {
}

// Map of CI environment variable identifiers to CI names
const CI_ENV: {[key: string]: string} = {
const CI_ENV: { [key: string]: string } = {
// https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables
GITHUB_ACTIONS: "GITHUB_ACTIONS",
// https://docs.gitlab.com/ee/ci/variables/predefined_variables.html
Expand All @@ -22,15 +22,15 @@ const CI_ENV: {[key: string]: string} = {
TEAMCITY_VERSION: "TEAMCITY",
// https://docs.aws.amazon.com/codepipeline/latest/userguide/reference-variables.html
CODEBUILD_BUILD_ID: "CODEBUILD",
}
};

export class CICollector extends Collector {
async collect(): Promise<CIData | undefined> {
for (const e in CI_ENV) {
if (e in process.env) {
return {name: CI_ENV[`${e}`]}
return { name: CI_ENV[`${e}`] };
}
}
return undefined;
}
}
}
7 changes: 4 additions & 3 deletions apps/wing/src/analytics/collectors/cli-collector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@ export class CLICollector extends Collector {
options: `${JSON.stringify(this.cmd.opts())}`,
version: PACKAGE_VERSION,
wing_sdk_version: this.tryGetModuleVersion("@winglang/sdk/package.json"),
wing_console_version: this.tryGetModuleVersion(`@wingconsole/app/package.json`)
}
wing_console_version: this.tryGetModuleVersion(`@wingconsole/app/package.json`),
};
}

private tryGetModuleVersion(module: string): string | undefined {
try {
// eslint-disable-next-line @typescript-eslint/no-require-imports
return require(module).version as string;
} catch (error) {
return undefined;
}
}
}
}
4 changes: 2 additions & 2 deletions apps/wing/src/analytics/collectors/collector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export interface Data {
export abstract class Collector {
abstract collect(): Promise<Data | undefined>;

protected async runCommand(cmd: string, args: string[], dir: string = '.'): Promise<any> {
protected async runCommand(cmd: string, args: string[], dir: string = "."): Promise<any> {
try {
const raw = await new Promise((resolve, reject) => {
execFile(cmd, args, { cwd: dir }, (error, stdout, stderr) => {
Expand All @@ -25,4 +25,4 @@ export abstract class Collector {
return "";
}
}
}
}
Loading

0 comments on commit 0e8e85f

Please sign in to comment.