Merge pull request #693 from quicktype/telemetry-ci

If running on CI, create a stable userId based on the project
This commit is contained in:
David Siegel 2018-03-21 15:08:24 -07:00 коммит произвёл GitHub
Родитель 3d5464e5f5 abca16b326
Коммит 558a6e376f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 5842 добавлений и 13 удалений

5752
package-lock.json сгенерированный

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -9,7 +9,7 @@
"pub": "script/publish.sh",
"prepare": "npm run build",
"build": "script/build.ts",
"test": "npm run build && script/test",
"test": "npm run build && jest && script/test",
"start": "script/watch",
"pkg": "script/make-pkgs.sh",
"tslint": "tslint --project src"
@ -41,6 +41,7 @@
"@types/graphql": "^0.11.7",
"@types/handlebars": "^4.0.36",
"@types/is-url": "^1.2.28",
"@types/jest": "^22.2.0",
"@types/js-base64": "^2.3.1",
"@types/lodash": "^4.14.72",
"@types/node": "^8.0.19",
@ -57,16 +58,28 @@
"exit": "^0.1.2",
"flow-bin": "^0.66.0",
"flow-remove-types": "^1.2.3",
"jest": "^22.4.3",
"promise-timeout": "^1.1.1",
"shelljs": "^0.7.8",
"ts-jest": "^22.4.2",
"ts-node": "^3.3.0",
"tslint": "^5.8.0",
"typescript": "^2.5.3",
"uglify-js": "^3.0.26",
"watch": "^1.0.2"
},
"files": [
"dist/**"
],
"bin": "dist/cli/index.js"
"files": ["dist/**"],
"bin": "dist/cli/index.js",
"jest": {
"transform": {
"^.+\\.tsx?$": "ts-jest"
},
"globals": {
"ts-jest": {
"tsConfigFile": "src/tsconfig.json"
}
},
"testRegex": "(/__tests__/.*)\\.test\\.(tsx?)$",
"moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"]
}
}

Просмотреть файл

@ -0,0 +1,27 @@
import * as ci from "../../cli/ci";
describe("tryHash", () => {
it("should get undefined if any parameter is", () => {
const hash = ci.tryHash(["hello", undefined, "world"]);
expect(hash).toBeUndefined();
});
it("should get a string if all parameters are", () => {
const hash = ci.tryHash(["hello", "world"]);
expect(typeof hash).toBe("string");
});
});
describe("getProvider", () => {
it("should get a provider for Travis", () => {
const provider = ci.getProvider({
TRAVIS_REPO_SLUG: "quicktype/quicktype"
});
expect(provider && provider.provider).toBe("Travis");
});
it("should get undefined provider for empty environment", () => {
const provider = ci.getProvider({});
expect(provider).toBeUndefined();
});
});

Просмотреть файл

@ -1,5 +1,6 @@
import * as ga from "universal-analytics";
import * as storage from "./storage";
import * as ci from "./ci";
const uuid = require("uuid/v4");
@ -29,8 +30,18 @@ export class GoogleAnalytics implements Analytics {
private readonly visitor: ga.Visitor;
constructor() {
const userId = storage.get("userId", uuid());
const ciInfo = ci.getProvider();
const userId = ciInfo !== undefined ? ciInfo.userId : storage.get("userId", uuid());
this.visitor = ga(GoogleAnalyticsID, userId);
if (ciInfo !== undefined) {
this.ciProvider = ciInfo.provider;
}
}
set ciProvider(provider: string) {
this.visitor.set("dimension1", provider);
}
pageview(page: string): void {
@ -52,4 +63,4 @@ export class GoogleAnalytics implements Analytics {
this.visitor.event(category, action).send();
}
}
}
}

38
src/cli/ci.ts Normal file
Просмотреть файл

@ -0,0 +1,38 @@
import * as process from "process";
import { createHash } from "crypto";
// A map from CI providers to environment variables that uniquely identify a project.
// If present, these variables are hashed to produce a unique userId for quicktype in CI.
function getProviders(env: any = process.env): [string, Array<string | undefined>][] {
return [
["Travis", [env.TRAVIS_REPO_SLUG]],
["Jenkins", [env.JENKINS_URL]],
["TeamCity", [env.TEAMCITY_PROJECT_NAME]],
["CircleCI", [env.CIRCLE_PROJECT_USERNAME, env.CIRCLE_PROJECT_REPONAME]],
["Codeship", [env.CI_REPO_NAME]],
["GitLab", [env.GITLAB_CI, env.CI_REPOSITORY_URL, env.CI_PROJECT_ID]],
["VSTS", [env.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI, env.BUILD_REPOSITORY_NAME]],
["App Center", [env.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI, env.BUILD_REPOSITORY_NAME]],
// We intentionally collapse users with env.CI to prevent over-counting for unidentified CI
["Other", [env.CI]]
];
}
export function tryHash(envs: Array<string | undefined>): string | undefined {
if (envs.some(s => s === undefined)) {
return undefined;
}
const hash = createHash("sha256");
envs.forEach(s => hash.update(s as string));
return hash.digest("base64");
}
export function getProvider(environment?: any): { provider: string; userId: string } | undefined {
for (const [provider, vars] of getProviders(environment)) {
const hash = tryHash(vars);
if (hash !== undefined) {
return { provider, userId: hash };
}
}
return undefined;
}