{"id":17058127,"url":"https://github.com/onigoetz/absorption","last_synced_at":"2025-04-12T17:44:27.227Z","repository":{"id":36967171,"uuid":"245791730","full_name":"onigoetz/absorption","owner":"onigoetz","description":"Calculate absorption on your repositories","archived":false,"fork":false,"pushed_at":"2025-04-05T19:01:27.000Z","size":5081,"stargazers_count":8,"open_issues_count":4,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-05T20:18:35.341Z","etag":null,"topics":["code-metrics","metrics"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/absorption","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/onigoetz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-08T10:10:49.000Z","updated_at":"2025-03-27T19:39:39.000Z","dependencies_parsed_at":"2023-12-23T08:38:38.185Z","dependency_job_id":"c884383a-01e4-4485-9bf5-0c281a41a0c7","html_url":"https://github.com/onigoetz/absorption","commit_stats":{"total_commits":150,"total_committers":5,"mean_commits":30.0,"dds":0.3866666666666667,"last_synced_commit":"4102c869762fafe3fbe8fe7009a71106ae8a44c7"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onigoetz%2Fabsorption","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onigoetz%2Fabsorption/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onigoetz%2Fabsorption/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onigoetz%2Fabsorption/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/onigoetz","download_url":"https://codeload.github.com/onigoetz/absorption/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248609387,"owners_count":21132901,"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":["code-metrics","metrics"],"created_at":"2024-10-14T10:28:55.688Z","updated_at":"2025-04-12T17:44:27.206Z","avatar_url":"https://github.com/onigoetz.png","language":"JavaScript","readme":"# Absorption\n\n[![Latest Version](https://img.shields.io/github/release/onigoetz/absorption.svg?style=flat-square)](https://github.com/onigoetz/absorption/releases)\n[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](https://github.com/onigoetz/absorption/blob/master/LICENSE.md)\n![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/onigoetz/absorption/nodejs.yml?style=flat-square\u0026logo=github)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=onigoetz_absorption\u0026metric=coverage)](https://sonarcloud.io/dashboard?id=onigoetz_absorption)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=onigoetz_absorption\u0026metric=alert_status)](https://sonarcloud.io/dashboard?id=onigoetz_absorption)\n[![NPM Downloads](https://img.shields.io/npm/dw/absorption?style=flat-square\u0026logo=npm)](https://www.npmjs.com/package/absorption)\n\n## What is absorption ?\n\nAbsorption is a small tool that gives you a knowledge absorption score for a git repository.\n\nThis is an approach to answer the questions **Who has the knowledge on this repository?** and **What is the bus factor on this repository?**\n\nLike all one dimension metric, this metric is not a silver bullet, by using the last person to modifiy a line of code to define it's owner, we will for example miscalculate if there was a mass reformating on the repository.\nAlso, since we are not language aware, we will measure empty lines and there is no notion of importance of a file.\n\n## How does it work ?\n\nThe approach we take is for each file in a repository, gather how many lines were written per contributor and when.\n\nThen by using a thresold date (1 year by default) we sort the elements in two buckets : commits made before the thresold and commits made after.\n\nThis allows us to go in the last step of the process, sorting all those commits in three categories :\n\n- Fresh : Code that was modified recently (after the thresold)\n- Fading : Code that was modified before the threshold but by a contributor who was also active more recently\n- Lost : Code that was modified by somebody no longer active on the repository\n\nThis, in turn will give you a bus factor : How many people need to stop commiting on a project for it to be in danger.\nBy default\n\n## Installation\n\n```bash\nnpm install -g absorption\n```\n\n## How to use it\n\n```bash\nabsorption /absolute/path/to/cloned/repository\n```\n\nWill give you useful information already.\nYou can then use the options of the command to fine tune the results.\n\n- `--threshold 6m` After what delay do you consider the knowledge lost. starts with a number, followed by 'd' for days, 'w' for weeks, 'm' for months or 'y' for years (1y, 6m, 9w). Defaults to one year.\n- `--contributors contributors.json` Feed data on contributors, see below for that file's format.\n- `--weights weights.json` Feed data on file weights, see below for that file's format.\n- `--with-media` Media files (images, audio and video) are excluded by default from the scan, setting `--with-media` will include them.\n- `--with-lockfiles` Lockfiles (`package-lock.json`, `yarn.lock`, `composer.lock`) are excluded by default from the scan, setting `--with-lockfiles` will include them.\n- `--verbose` Output lots of debug information\n- `--json file.json` Output the raw data to a json file. (used in conjunction with `--verbose` will output raw data per file as well)\n- `--max-contributors 10` Allows to customize the number of active contributors displayed in the table (default: 10)\n- `--max-lost-contributors 10` Allows to customize the number of lost contributors displayed in the list (default: 10)\n- `--branch` The branch of repository to scan (default: master)\n\n\nA more advanced example :\n\n```\nabsorption /Users/onigoetz/Sites/Libs/crafty --weights weights.json --contributors contributors.json\nScanning ████████████████████████████████████████ | 100% | 492/492 files\n\nThe repository's absorption score is 16% fresh, 84% fading and 0% lost\n\nFresh/Fading knowledge\n\n Name               │    Total │    Fresh │   Fading \n────────────────────┼──────────┼──────────┼──────────\n Stéphane Goetz     │  99.51 % │  15.67 % │  83.83 % \n Vitalii Shapovalov │   0.14 % │   0.14 % │   0.00 % \n\n\nLost knowledge\n\n Name                                │    Total \n─────────────────────────────────────┼──────────\n Illia Shestakov                     │   0.19 % \n Marie P-W \u003cmarie.wermuth@gmail.com\u003e │   0.08 % \n Jonas Renaudot                      │   0.05 % \n mindhalt \u003cmindhalt@gmail.com\u003e       │   0.03 % \n```\n\n### `--contributors contributors.json`\n\n```json\n[\n  {\n    \"type\": \"person\",\n    \"name\": \"Stéphane Goetz\",\n    \"active\": true,\n    \"identities\": [\n      \"Stéphane Goetz \u003conigoetz@onigoetz.ch\u003e\",\n      \"Stéphane Goetz \u003cstephane.goetz@swissquote.ch\u003e\",\n      \"Stéphane Goetz \u003cstephane.goetz@onigoetz.ch\u003e\"\n    ]\n  },\n  {\n    \"type\": \"bot\",\n    \"name\": \"Renovate\",\n    \"identities\": [\"Renovate Bot \u003cbot@renovateapp.com\u003e\"]\n  }\n]\n```\n\nThe fields:\n\n- `type`: \"person\" or \"bot\", bots will be excluded from the output.\n- `name`: This name will be used for display.\n- `active`: (Optional) Setting this value to true, will move lost knowledge to \"fading\" knowledge and if false, will move \"fresh\" and \"fading\" knowledge to \"lost\"\n- `identities`: The list of elements to match the contributors to.\n\n### `--weights weights.json`\n\nThe weight that is given to each file can be fine tuned, for example you might want to give a higher ranking to some critical business code in an application. Or give only half the weight to tests.\n\nA weight of `0` for a file will skip its processing entirely.\n\n```json\n{\n  \"**/__tests__/*\": 0.5,\n  \"src/business/**\": 2,\n  \"**/*.js\": 1.5\n}\n```\n\n## How fast is it ?\n\nWe have to run a `git blame` on every file on a repository, on small to medium repositories it takes a few seconds to one minute, on big repositories this can take a few minutes. (I ran it on github.com/babel/babel, with 18'000 files it took a little over 6 minutes on my Mac Mini)\n\nNow the good news is that we create an incremental cache, if you rerun the command, all files that weren't modified can be read from cache.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonigoetz%2Fabsorption","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fonigoetz%2Fabsorption","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonigoetz%2Fabsorption/lists"}