100 lines
3.3 KiB
Markdown
100 lines
3.3 KiB
Markdown
# @foss.global/codefeed
|
|
|
|
Generate an activity feed from a Gitea instance. Scans orgs and repos, retrieves commits since a configurable timestamp, enriches with tags, optional npm publish detection, and CHANGELOG snippets.
|
|
|
|
## Install
|
|
|
|
```bash
|
|
pnpm add @foss.global/codefeed
|
|
# or
|
|
npm i @foss.global/codefeed
|
|
```
|
|
|
|
Requires Node.js 18+ (global fetch/Request/Response) and ESM.
|
|
|
|
## Quick Start
|
|
|
|
```ts
|
|
import { CodeFeed } from '@foss.global/codefeed';
|
|
|
|
// Fetch commits since one week ago (default), no caching
|
|
const feed = new CodeFeed('https://code.example.com', 'gitea_token');
|
|
const commits = await feed.fetchAllCommitsFromInstance();
|
|
console.log(commits);
|
|
```
|
|
|
|
### With options
|
|
|
|
```ts
|
|
const thirtyDays = 30 * 24 * 60 * 60 * 1000;
|
|
const since = new Date(Date.now() - thirtyDays).toISOString();
|
|
|
|
const feed = new CodeFeed('https://code.example.com', 'gitea_token', since, {
|
|
enableCache: true, // keep results in memory
|
|
cacheWindowMs: thirtyDays, // trim cache to this window
|
|
enableNpmCheck: true, // check npm for published versions
|
|
taggedOnly: false, // return all commits (or only tagged)
|
|
orgAllowlist: ['myorg'], // only scan these orgs
|
|
orgDenylist: ['archive'], // skip these orgs
|
|
repoAllowlist: ['myorg/app1', 'myorg/app2'], // only these repos
|
|
repoDenylist: ['myorg/old-repo'], // skip these repos
|
|
untilTimestamp: new Date().toISOString(), // optional upper bound
|
|
verbose: true, // print a short metrics summary
|
|
});
|
|
|
|
const commits = await feed.fetchAllCommitsFromInstance();
|
|
```
|
|
|
|
Each returned item follows this shape:
|
|
|
|
```ts
|
|
interface ICommitResult {
|
|
baseUrl: string;
|
|
org: string;
|
|
repo: string;
|
|
timestamp: string; // ISO date
|
|
hash: string; // commit SHA
|
|
commitMessage: string;
|
|
tagged: boolean; // commit is pointed to by a tag
|
|
publishedOnNpm: boolean; // only when npm check enabled and tag matches
|
|
prettyAgoTime: string; // human-readable diff
|
|
changelog: string | undefined; // snippet for matching tag version
|
|
}
|
|
```
|
|
|
|
## Features
|
|
|
|
- Pagination for orgs, repos, commits, and tags (no missing pages)
|
|
- Retries with exponential backoff for 429/5xx and network errors
|
|
- CHANGELOG discovery with case variants (`CHANGELOG.md`, `changelog.md`, `docs/CHANGELOG.md`)
|
|
- Tag-to-version mapping based on tag names (`vX.Y.Z` → `X.Y.Z`)
|
|
- Optional npm publish detection via `@org/repo` package versions
|
|
- In-memory caching with window trimming and stable sorting
|
|
- Allow/deny filters for orgs and repos, optional time upper bound
|
|
- One-line metrics summary when `verbose: true`
|
|
|
|
## Environment
|
|
|
|
- Gitea base URL and an optional token with read access
|
|
- Node.js 18+ (global fetch)
|
|
|
|
## Testing
|
|
|
|
The repo contains:
|
|
- An integration test using a `GITEA_TOKEN` from `.nogit/` via `@push.rocks/qenv`.
|
|
- A mocked pagination test that does not require network.
|
|
|
|
Run tests:
|
|
|
|
```bash
|
|
pnpm test
|
|
```
|
|
|
|
For the integration test, ensure `GITEA_TOKEN` is provided (e.g., via `.nogit/` as used in `test/test.ts`).
|
|
|
|
## Notes
|
|
|
|
- When `taggedOnly` is enabled, the feed includes only commits associated with tags.
|
|
- `publishedOnNpm` is computed by matching the tag-derived version against the npm registry for `@org/repo`.
|
|
- For very large instances, consider using allowlists/denylists and enabling caching for incremental runs.
|