Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# These organizations support the ILN Frontend project
github: [Invoice-Liquidity-Network]

# Drips Network Wave funding
custom:
- https://drips.network/waves
66 changes: 66 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Automatic PR labeling based on changed file paths
# Labels are applied when a PR touches files in the specified paths

ci:
- .github/workflows/**/*
- .github/labeler.yml
- .github/dependabot.yml
- .github/CODEOWNERS
- .husky/**/*
- .gitcliff.toml
- eslint.config.mjs
- prettierrc
- vitest.config.ts
- playwright.config.ts
- stryker.conf.json
- .lighthouserc.json

documentation:
- docs/**/*
- README.md
- CONTRIBUTING.md
- DESIGN.md
- SECURITY.md
- CHANGELOG.md
- PR_NEW.md

testing:
- __tests__/**/*
- e2e/**/*
- vitest.setup.ts
- vitest.shims.d.ts

ui:
- src/components/**/*
- src/app/**/page.tsx
- src/app/**/layout.tsx
- styles/**/*

hooks:
- src/hooks/**/*
- src/context/**/*

contracts:
- src/lib/soroban.ts
- src/lib/horizon.ts
- src/lib/indexer-websocket.ts
- src/lib/contract/**/*
- src/lib/invoice-nft.ts

api:
- app/api/**/*

utils:
- src/utils/**/*
- src/lib/**/* # (excluding contract-specific files above)

types:
- src/types/**/*
- src/constants.ts

dependencies:
- package.json
- pnpm-lock.yaml
- tsconfig.json
- next.config.ts
- postcss.config.mjs
26 changes: 26 additions & 0 deletions .github/workflows/pr-labeler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Pull Request Labeler

on:
pull_request_target:
types: [opened, edited, synchronize, reopened]

permissions:
contents: read
pull-requests: write

jobs:
labeler:
name: Apply labels based on changed files
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}

- name: Run Labeler
uses: actions/labeler@v5
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
configuration-path: .github/labeler.yml
sync-labels: true
155 changes: 155 additions & 0 deletions .github/workflows/stale-assignments.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
name: Stale Assignment Reclaimer

on:
schedule:
# Run daily at 00:00 UTC
- cron: '0 0 * * *'
workflow_dispatch:

permissions:
issues: write
pull-requests: write

jobs:
stale-assignments:
name: Reclaim abandoned issue assignments
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Reclaim stale assignments
uses: actions/github-script@v7
with:
script: |
const { Octokit } = require('@octokit/rest');
const octokit = new Octokit({ auth: github.token });

// Configuration (can be adjusted here)
const WARNING_DAYS = 7; // Days before warning comment
const RECLAIM_DAYS = 14; // Days before unassignment
const WARNING_LABEL = 'stale-assignment-warning';
const RECLAIM_LABEL = 'assignment-reclaimed';

const owner = context.repo.owner;
const repo = context.repo.repo;

// Get all open issues with assignees
const issues = await octokit.rest.issues.listForRepo({
owner,
repo,
state: 'open',
assignee: '*',
per_page: 100
});

const now = new Date();

for (const issue of issues.data) {
const assignees = issue.assignees.map(a => a.login);
if (assignees.length === 0) continue;

const assignedAt = new Date(issue.created_at);
const updatedAt = new Date(issue.updated_at);
const daysSinceUpdate = Math.floor((now - updatedAt) / (1000 * 60 * 60 * 24));
const daysSinceAssignment = Math.floor((now - assignedAt) / (1000 * 60 * 60 * 24));

// Check if there's a linked PR
const hasLinkedPR = issue.body?.includes('Closes') ||
issue.body?.includes('Fixes') ||
issue.body?.includes('Resolves') ||
issue.body?.includes('#');

// Check if there are open PRs referencing this issue
const prs = await octokit.rest.pulls.list({
owner,
repo,
state: 'open',
per_page: 100
});

const linkedPR = prs.data.find(pr =>
pr.body?.includes(`#${issue.number}`) ||
pr.title.includes(`#${issue.number}`)
);

// Skip if there's active PR activity
if (linkedPR) {
console.log(`Issue #${issue.number} has active PR #${linkedPR.number} - skipping`);
continue;
}

// Check for existing labels
const hasWarningLabel = issue.labels.some(l => l.name === WARNING_LABEL);
const hasReclaimLabel = issue.labels.some(l => l.name === RECLAIM_LABEL);

// Stage 1: Warning comment
if (daysSinceUpdate >= WARNING_DAYS && !hasWarningLabel && !hasReclaimLabel) {
const warningComment = "⚠️ **Stale Assignment Warning**\n\n" +
"This issue has been assigned to @" + assignees.join(', @') + " for " + daysSinceAssignment + " days with no linked PR activity for " + daysSinceUpdate + " days.\n\n" +
"To keep this assignment active, please:\n" +
"1. Open a draft PR if you're working on it\n" +
"2. Comment with an update on your progress\n" +
"3. Unassign yourself if you're no longer working on it\n\n" +
"If no activity is detected within " + (RECLAIM_DAYS - WARNING_DAYS) + " days, the assignment will be automatically removed to allow others to claim this issue.\n\n" +
"---\n" +
"*This is an automated message. Contact maintainers if you believe this is an error.*";

await octokit.rest.issues.createComment({
owner,
repo,
issue_number: issue.number,
body: warningComment
});

await octokit.rest.issues.addLabels({
owner,
repo,
issue_number: issue.number,
labels: [WARNING_LABEL]
});

console.log("Added warning to issue #" + issue.number);
}

// Stage 2: Reclaim assignment
if (daysSinceUpdate >= RECLAIM_DAYS && !hasReclaimLabel) {
const reclaimComment = "🔄 **Assignment Reclaimed**\n\n" +
"This issue was previously assigned to @" + assignees.join(', @') + " but has shown no activity for " + daysSinceUpdate + " days.\n\n" +
"The assignment has been automatically removed to allow other contributors to claim this issue. If you were still working on it, please re-assign yourself and open a PR promptly.\n\n" +
"---\n" +
"*This is an automated message. Contact maintainers if you believe this is an error.*";

await octokit.rest.issues.createComment({
owner,
repo,
issue_number: issue.number,
body: reclaimComment
});

// Remove all assignees
await octokit.rest.issues.removeAssignees({
owner,
repo,
issue_number: issue.number,
assignees: assignees
});

// Update labels
await octokit.rest.issues.removeLabel({
owner,
repo,
issue_number: issue.number,
name: WARNING_LABEL
}).catch(() => {}); // Ignore if label doesn't exist

await octokit.rest.issues.addLabels({
owner,
repo,
issue_number: issue.number,
labels: [RECLAIM_LABEL]
});

console.log("Reclaimed assignment for issue #" + issue.number);
}
}
38 changes: 38 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,44 @@ When you open a PR, GitHub will automatically suggest reviewers based on the fil

If you become a regular contributor to a specific area of the codebase, you can request to be added as a code owner. Contact a maintainer to discuss this.

## Stale Assignment Policy

To maintain effective Wave throughput and ensure issues don't get claimed and abandoned, this repository uses an automated stale assignment reclaimer.

### How It Works

The stale assignment bot runs daily and monitors assigned issues:

1. **Warning Stage (7 days of inactivity)**
- If an issue has been assigned for 7+ days with no linked PR activity, a warning comment is added
- The issue is labeled with `stale-assignment-warning`
- The assignee is notified with instructions to either:
- Open a draft PR
- Comment with a progress update
- Unassign themselves if no longer working on it

2. **Reclaim Stage (14 days of inactivity)**
- If no activity is detected for 14+ days, the assignment is automatically removed
- The issue is labeled with `assignment-reclaimed`
- Other contributors can then claim the issue

### Configuration

The timeout periods are configurable in `.github/workflows/stale-assignments.yml`:
- `WARNING_DAYS`: Days before warning comment (default: 7)
- `RECLAIM_DAYS`: Days before unassignment (default: 14)

### For Contributors

- **When claiming an issue**: Open a draft PR within 7 days to show active work
- **If you need more time**: Comment on the issue with a progress update to reset the timer
- **If you can't complete it**: Unassign yourself promptly so others can claim it
- **After reclamation**: If your assignment was reclaimed but you're still working on it, re-assign yourself and open a PR promptly

### Exemptions

Issues with linked open PRs are automatically exempt from the stale assignment check.

## Code of Conduct

Please be respectful and constructive in all interactions. We aim to create a welcoming environment for all contributors.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ The analytics view brings together yield, volume, and market trends for deeper p

## 🔗 Useful Links & Documentation

- **Documentation Index**: Browse all project documentation in [docs/README.md](docs/README.md).
- **Getting Started Guide**: Refer to the [Quick Start](#-quick-start) section.
- **Developer Quickstart**: Follow the full setup guide in [docs/developer-quickstart.md](docs/developer-quickstart.md).
- **Component Library (Storybook)**: Browse the full component library with interactive controls, variants, and a11y checks at the [published Storybook](https://invoice-liquidity-network.github.io/ILN-Frontend) (deployed from `main`).
Expand Down
35 changes: 35 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Documentation Index

This directory contains comprehensive documentation for the ILN Frontend project.

## Core Documentation

- **[architecture.md](architecture.md)** - Frontend architecture overview covering design decisions, folder structure, data flow patterns, and architectural trade-offs. Essential for understanding the codebase structure and development conventions.

- **[developer-quickstart.md](developer-quickstart.md)** - Step-by-step guide from fresh clone to running local development environment. Covers prerequisites, installation, and initial setup for all platforms.

## Testing & Quality Assurance

- **[testing.md](testing.md)** - Comprehensive testing guide covering unit tests (Vitest), end-to-end tests (Playwright), and testing best practices.

- **[VISUAL_REGRESSION_WORKFLOW.md](VISUAL_REGRESSION_WORKFLOW.md)** - Explains the Chromatic visual regression testing workflow, including how to approve/reject UI changes and add new Storybook stories.

- **[LIGHTHOUSE_CI.md](LIGHTHOUSE_CI.md)** - Documentation for Lighthouse CI performance budget tests, including performance thresholds, tested pages, and how to review reports.

## CI/CD & Infrastructure

- **[ci-cd.md](ci-cd.md)** - CI/CD pipeline documentation covering GitHub Actions workflows, deployment processes, and self-hosted runner configuration.

## Domain-Specific Documentation

- **[contract-fixtures.md](contract-fixtures.md)** - Documentation for contract test fixtures used in integration testing with Stellar smart contracts.

- **[repo-size-audit.md](repo-size-audit.md)** - Repository size analysis and optimization recommendations for maintaining a lean codebase.

## Hooks Documentation

- **[hooks/](hooks/)** - Detailed documentation for custom React hooks, including usage examples and API references.

---

**Note**: This index should be updated whenever new documentation is added to the `docs/` directory to maintain discoverability.
Loading