{"id":23131660,"url":"https://github.com/peopledoc/perfo","last_synced_at":"2025-08-14T21:03:38.317Z","repository":{"id":34433020,"uuid":"153141860","full_name":"peopledoc/perfo","owner":"peopledoc","description":"CI Performance analysis tool","archived":false,"fork":false,"pushed_at":"2024-01-12T23:12:28.000Z","size":4234,"stargazers_count":1,"open_issues_count":18,"forks_count":0,"subscribers_count":35,"default_branch":"master","last_synced_at":"2025-05-20T16:53:33.013Z","etag":null,"topics":["approved-public","circleci","ember-app","ghec-mig-migrated","perfomance","performance-analysis","performance-tools","performance-visualization","tribe-js"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/peopledoc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-10-15T15:57:20.000Z","updated_at":"2023-09-27T19:10:20.000Z","dependencies_parsed_at":"2025-02-09T18:40:45.301Z","dependency_job_id":null,"html_url":"https://github.com/peopledoc/perfo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/peopledoc/perfo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peopledoc%2Fperfo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peopledoc%2Fperfo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peopledoc%2Fperfo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peopledoc%2Fperfo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/peopledoc","download_url":"https://codeload.github.com/peopledoc/perfo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peopledoc%2Fperfo/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266143941,"owners_count":23883069,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["approved-public","circleci","ember-app","ghec-mig-migrated","perfomance","performance-analysis","performance-tools","performance-visualization","tribe-js"],"created_at":"2024-12-17T11:15:48.707Z","updated_at":"2025-07-20T15:02:57.044Z","avatar_url":"https://github.com/peopledoc.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# perfo\n\nperfo is an app that shows build performance from CI providers.\n\n## Usage\n\n### Prerequisites\n\nYou will need the following things properly installed on your computer.\n\n* [Git](https://git-scm.com/)\n* [Node.js](https://nodejs.org/) 11+\n* [Yarn](https://yarnpkg.com/)\n* [Ember CLI](https://ember-cli.com/)\n\n### Installation\n\n* `git clone git@github.com:peopledoc/perfo`\n* `cd perfo`\n* `yarn`\n\n### Running\n\nNote that perfo includes not only a front ember app, but also an express server\nthat is used to query CI providers for data and store user preferences.\n\nTo reduce strain on external CI APIs (and maybe avoid rate limiting), the server\ncaches data requested from them in a filesystem-based cache.  You can control\nthat cache with environment variables.\n\nYou will need the following environment variables to run the app:\n\n* `PERFO_CIRCLECI_TOKEN`: a [CircleCI API token][cciapi]\n\nOptionally, you may also set the following environment variables:\n\n* `PERFO_CACHE_VALIDITY`: the server cache validity in milliseconds; defaults to\n  30 minutes\n* `PERFO_CACHE_PRUNE_INTERVAL`: the interval at which the whole cache content is\n  checked for validity and expired items are removed; defaults to the cache\n  validity value\n* `PERFO_DATA_DIR`: the path where the server stores cache and stored data;\n  defaults to a `data` directory at the project root\n* `PERFO_LOG_FORMAT`: format for [morgan][morgan] logs; defaults to `dev`\n* `PERFO_MAX_BUILD_AGE`: maximum age (in milliseconds) of builds to show data\n  from; defaults to 3 months\n* `PERFO_ORG_FILTER`: if set, only make projects visible when their org is set\n  to this value; defaults to no filter\n* `PERFO_PORT`: TCP port the server listens on; only used in production (the\n  development server will always use the port passed to `ember serve` or 4200 as\n  a default value); defaults to 4200\n* `PERFO_ROOT_URL`: the root URL where the app is served; defaults to `/`\n\n#### Development\n\n* `ember serve`\n* Visit your app at [http://localhost:4200](http://localhost:4200)\n\n#### Production\n\nYou will need a webserver that is capable of serving static files from a\ndirectory and proxying requests to a locally-running HTTP server.\n\n* Build the app: `ember build --environment=production`\n  * make sure the `PERFO_ROOT_URL` environment is set during the build to the\n    value that will be used when executing the server\n  * set up your webserver to serve the `dist` directory (or whichever directory\n    you told `ember build` to output into) at the root URL.\n* Run `server/standalone.js` with node 11+\n  * make sure environment variables are set properly\n  * make sure the user running the server can read and write into the directory\n    pointed by `PERFO_DATA_DIR`\n  * you may want to use a process manager to ensure it keeps running.\n  * set up your webserver to proxy requests that did not hit a static file to\n    where the server is listening (̀`localhost:PERFO_PORT`).\n\n### Custom graphs\n\nperfo automatically displays a build duration graph for projects (with one line\nper build job) over time.  Users can also define custom graphs for each project.\n\nTo use custom graphs, your build jobs must generate JSON artifacts that contain\nan array of data points, each data point being an object with a string `label`\nand a numeric `value`.\n\nWhen defining a custom graph, users set the following properties:\n\n* A title for the graph\n* The build job name that generates the artifacts\n* A regexp for branches where the graph applies\n* A regexp for the name of the artifact to look for\n* A formatter for data values (none, duration, file size)\n* A graph type (line, smooth line, stacked area)\n\nWhen drawing the graph, perfo will look for all builds that match the job name\nand have an artifact that matches the regexp.  It will fetch data for all those\nartifacts and draw a curve for each distinct `label` value found in those.\n\nFor example, you could imagine having a custom graph drawing the evolution of\nyour static asset sizes over time by having a build job generate a JSON artifact\nwith the following content:\n\n```js\n[\n  { 'label': 'vendor.js', 'value': 12345 },\n  { 'label': 'vendor.css', 'value': 23456 },\n  { 'label': 'app.js', 'value': 34567 },\n  { 'label': 'app.css', 'value': 45678 }\n]\n```\n\n### Extending perfo\n\n#### Adding new CI providers\n\nperfo comes with a CircleCI provider.  You may add new providers to the\n`server/providers` directory and they will be used automatically by the server\n(after a restart).\n\n##### Provider API\n\nA provider is a module that exports a single provider factory function.  This\nfunction must return an object with the methods as described below.\n\nAll methods must be `async` (or return a promise).  Objects returned may have\nadditional keys than those specified below, but to ensure there are no name\nclashes with properties that may be added later to the provider API, you must\nprefix any \"private\" property with an underscore.\n\n**`async info()`: return information about the provider.**\n\nMust return an object with the following keys:\n\n* `account`: an identifier for the provider user (user ID, e-mail...)\n* `connected`: boolean indicating whether the provider is able to reach its data\n  source\n* `icon` (optional): URL for an icon to display for the provider\n* `name`: a human-readable name for the data source\n\n**`async projects()`: return the list of projects available**\n\nMust return an array of project objects, with the following keys:\n\n* `id`: a unique ID (within the scope of the provider) for the project\n* `name`: a human-readable name for the project\n* `branches`: an array of branch names for the project\n\n**`async builds(project, branch)`: return the list of available builds for a\nbranch of a project**\n\nParameters:\n\n* `project` is the project ID\n* `branch` is the branch name\n\nMust return an array of build objects, with the following keys:\n\n* `id`: a unique ID (within the scope of the project) for the build\n* `job`: a job name for the build (eg. \"test\", \"build\"...)\n* `start`: the starting date for the build as an ISO string\n* `duration`: the duration of the build in milliseconds\n* `subject`: the subject of this specific build (eg. a commit message)\n* `revision`: the VCS revision for this specific build (eg. a commit SHA-1)\n\n**`async customGraphData(project, branch, jobName, artifactMatches)`: return a\nlist of datasets to draw a custom graph for a branch of a project**\n\nParameters:\n\n* `project` is the project ID\n* `branch` is the branch name\n* `jobName` is used to filter builds to extract data from\n* `artifactRegex` is used to filter artifact names to extract data from\n\nMust return an array of dataset objects, one per build that matches the\n`jobName` parameter and has an artifact whose name matches `artifactRegex`.  If\nseveral artifacts from a build match, use the first one.\n\nDataset objects have the following keys:\n\n* `date`: start date for the build\n* `subject`, `revision`: same values as the corresponding keys in the build\n* `points`: data from the first matching artifact in the build; should be an\n  array of objects with a string `label` and a numeric `value`.\n\n##### Injected services\n\nProvider factories will receive an `injections` object as their first parameter.\nThis object contains various services that providers may want to use, most\nnotably the following:\n\n**`config`: configuration data**\n\nContains the following keys:\n\n* `orgFilter`: organization filter to filter the project list\n* `maxBuildAge`: maximum age in milliseconds of project builds to consider\n\n**`async cache(key, async getter())`: get data from the server cache**\n\nLooks for a cached value with `key` as a key, and return it.\n\nThe key namespace is shared, so you should prefix your cache keys with the\nprovider name.  Use `path.join()` to build keys with several parts.\n\nIf the key is not available or the cache has expired, `getter()` will be called\nand its return value will be stored in the cache and returned.\n\n**`store`: local filesystem-backed data store**\n\nStores data on the filesystem in a directory structure as JSON files.  Any data\nyou store should be JSON-serializable.\n\nThe key namespace is shared, so you should prefix your store keys with the\nprovider name.  Use `path.join()` to build keys with several parts.\n\nThe store has the following methods:\n\n* `async getItem(key)`: gets an item from the store or return undefined\n* `async setItem(key, value)`: set an item in the store, overriding any existing\n  data\n* `async delItem(key)`: remove an item from the store\n* `async keys(path = '')`: list all keys in the store in a given path\n\n\u003e *Note: using cache vs. store?*\n\u003e\n\u003e When requesting data from a remote CI provider API, you should use the cache\n\u003e for resources that change over time (eg. project list, project builds) and\n\u003e the store for resources that do not change (eg. payload for a specific build\n\u003e artifact).\n\n**`logger`: very simple logging facility**\n\nHas the following methods:\n\n* `debug(item, ...)`: logs items to the console\n* `error(context, error)`: logs an error to the console\n\n---\n\n[cciapi]: https://circleci.com/account/api\n[morgan]: https://github.com/expressjs/morgan\n\n## License\n\nThis project is licensed under the [MIT License](LICENSE.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeopledoc%2Fperfo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpeopledoc%2Fperfo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeopledoc%2Fperfo/lists"}