feat: add maxSyncPeriod configuration to TFS settings
- Introduced maxSyncPeriod option in TfsConfigForm for user-defined synchronization duration. - Updated TfsService to filter pull requests based on the configured maxSyncPeriod. - Enhanced TfsPullRequest type to include 'rejected' status for better PR management. - Set default maxSyncPeriod to '90d' in user preferences and TFS configuration.
This commit is contained in:
@@ -15,6 +15,7 @@ export function TfsConfigForm() {
|
||||
personalAccessToken: '',
|
||||
repositories: [],
|
||||
ignoredRepositories: [],
|
||||
maxSyncPeriod: '90d',
|
||||
});
|
||||
const [isPending, startTransition] = useTransition();
|
||||
const [message, setMessage] = useState<{
|
||||
@@ -94,13 +95,14 @@ export function TfsConfigForm() {
|
||||
startTransition(async () => {
|
||||
setMessage(null);
|
||||
// Réinitialiser la config
|
||||
const resetConfig = {
|
||||
const resetConfig: TfsConfig = {
|
||||
enabled: false,
|
||||
organizationUrl: '',
|
||||
projectName: '',
|
||||
personalAccessToken: '',
|
||||
repositories: [],
|
||||
ignoredRepositories: [],
|
||||
maxSyncPeriod: '90d',
|
||||
};
|
||||
|
||||
const result = await saveTfsConfig(resetConfig);
|
||||
@@ -275,6 +277,14 @@ export function TfsConfigForm() {
|
||||
<span className="text-xs">Aucun</span>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-[var(--muted-foreground)]">
|
||||
Période max de sync:
|
||||
</span>{' '}
|
||||
<code className="bg-[var(--background)] px-2 py-1 rounded text-xs">
|
||||
{config?.maxSyncPeriod || '90d'}
|
||||
</code>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -475,6 +485,29 @@ export function TfsConfigForm() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-2">
|
||||
Période maximale de synchronisation
|
||||
</label>
|
||||
<select
|
||||
value={config.maxSyncPeriod || '90d'}
|
||||
onChange={(e) => updateConfig('maxSyncPeriod', e.target.value)}
|
||||
className="w-full px-3 py-2 border border-[var(--border)] rounded bg-[var(--background)] text-[var(--foreground)] focus:outline-none focus:ring-2 focus:ring-[var(--primary)] focus:border-transparent"
|
||||
>
|
||||
<option value="7d">7 jours</option>
|
||||
<option value="30d">30 jours</option>
|
||||
<option value="90d">90 jours (recommandé)</option>
|
||||
<option value="180d">180 jours</option>
|
||||
<option value="1y">1 an</option>
|
||||
<option value="2y">2 ans</option>
|
||||
<option value="3y">3 ans</option>
|
||||
</select>
|
||||
<p className="text-xs text-[var(--muted-foreground)] mt-1">
|
||||
Définit la période maximale pour récupérer les Pull Requests.
|
||||
Les PRs plus anciennes seront ignorées lors de la synchronisation.
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
|
||||
@@ -221,7 +221,7 @@ export interface TfsPullRequest {
|
||||
pullRequestId: number;
|
||||
title: string;
|
||||
description?: string;
|
||||
status: 'active' | 'completed' | 'abandoned';
|
||||
status: 'active' | 'completed' | 'abandoned' | 'rejected';
|
||||
createdBy: {
|
||||
displayName: string;
|
||||
uniqueName: string; // email
|
||||
|
||||
@@ -53,6 +53,7 @@ const DEFAULT_PREFERENCES: UserPreferences = {
|
||||
personalAccessToken: '',
|
||||
repositories: [],
|
||||
ignoredRepositories: [],
|
||||
maxSyncPeriod: '90d', // Par défaut 90 jours
|
||||
},
|
||||
tfsAutoSync: false,
|
||||
tfsSyncInterval: 'daily',
|
||||
|
||||
@@ -16,6 +16,7 @@ export interface TfsConfig {
|
||||
personalAccessToken?: string;
|
||||
repositories?: string[]; // Liste des repos à surveiller
|
||||
ignoredRepositories?: string[]; // Liste des repos à ignorer
|
||||
maxSyncPeriod?: '7d' | '30d' | '90d' | '180d' | '1y' | '2y' | '3y'; // Période maximale de synchronisation
|
||||
}
|
||||
|
||||
export interface TfsSyncAction {
|
||||
@@ -375,10 +376,10 @@ export class TfsService {
|
||||
|
||||
/**
|
||||
* Filtre les PRs par statut pertinent
|
||||
* - Garde toutes les PRs actives créées dans les 90 derniers jours
|
||||
* - Garde toutes les PRs actives créées dans la période configurée
|
||||
* - Garde les PRs completed récentes (moins de 30 jours)
|
||||
* - Exclut les PRs abandoned
|
||||
* - Exclut les PRs trop anciennes
|
||||
* - Exclut les PRs abandoned et rejected
|
||||
* - Exclut les PRs trop anciennes selon la configuration
|
||||
* - Exclut les PRs automatiques (Renovate, etc.)
|
||||
*/
|
||||
private filterByRelevantStatus(
|
||||
@@ -386,6 +387,11 @@ export class TfsService {
|
||||
): TfsPullRequest[] {
|
||||
const now = new Date();
|
||||
const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
|
||||
|
||||
// Calculer la période maximale selon la configuration
|
||||
const maxSyncPeriod = this.config.maxSyncPeriod || '90d';
|
||||
const maxSyncPeriodMs = this.getMaxSyncPeriodMs(maxSyncPeriod);
|
||||
const maxSyncDate = new Date(now.getTime() - maxSyncPeriodMs);
|
||||
|
||||
return pullRequests.filter((pr) => {
|
||||
// Exclure les PRs automatiques (Renovate, Dependabot, etc.)
|
||||
@@ -396,20 +402,20 @@ export class TfsService {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filtrer d'abord par âge - exclure les PRs trop anciennes
|
||||
// const createdDate = parseDate(pr.creationDate);
|
||||
// if (createdDate < ninetyDaysAgo) {
|
||||
// console.log(
|
||||
// `🗺 PR ${pr.pullRequestId} (${pr.title}): Trop ancienne (${formatDateForDisplay(createdDate)}) - EXCLUE`
|
||||
// );
|
||||
// return false;
|
||||
// }
|
||||
// Filtrer par âge selon la configuration
|
||||
const createdDate = parseDate(pr.creationDate);
|
||||
if (createdDate < maxSyncDate) {
|
||||
console.log(
|
||||
`🗺 PR ${pr.pullRequestId} (${pr.title}): Trop ancienne (${formatDateForDisplay(createdDate)}, limite: ${maxSyncPeriod}) - EXCLUE`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (pr.status.toLowerCase()) {
|
||||
case 'active':
|
||||
// PRs actives récentes
|
||||
// PRs actives dans la période configurée
|
||||
console.log(
|
||||
`✅ PR ${pr.pullRequestId} (${pr.title}): Active récente - INCLUSE`
|
||||
`✅ PR ${pr.pullRequestId} (${pr.title}): Active récente (${maxSyncPeriod}) - INCLUSE`
|
||||
);
|
||||
return true;
|
||||
|
||||
@@ -426,15 +432,52 @@ export class TfsService {
|
||||
|
||||
case 'abandoned':
|
||||
// PRs abandonnées ne sont pas pertinentes
|
||||
console.log(
|
||||
`❌ PR ${pr.pullRequestId} (${pr.title}): Abandonnée - EXCLUE`
|
||||
);
|
||||
return false;
|
||||
|
||||
case 'rejected':
|
||||
// PRs rejetées ne sont pas pertinentes
|
||||
console.log(
|
||||
`❌ PR ${pr.pullRequestId} (${pr.title}): Rejetée - EXCLUE`
|
||||
);
|
||||
return false;
|
||||
|
||||
default:
|
||||
// Statut inconnu, on l'inclut par précaution
|
||||
console.log(
|
||||
`⚠️ PR ${pr.pullRequestId} (${pr.title}): Statut inconnu "${pr.status}" - INCLUSE par précaution`
|
||||
);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Convertit une période de synchronisation en millisecondes
|
||||
*/
|
||||
private getMaxSyncPeriodMs(period: string): number {
|
||||
switch (period) {
|
||||
case '7d':
|
||||
return 7 * 24 * 60 * 60 * 1000; // 7 jours
|
||||
case '30d':
|
||||
return 30 * 24 * 60 * 60 * 1000; // 30 jours
|
||||
case '90d':
|
||||
return 90 * 24 * 60 * 60 * 1000; // 90 jours
|
||||
case '180d':
|
||||
return 180 * 24 * 60 * 60 * 1000; // 180 jours
|
||||
case '1y':
|
||||
return 365 * 24 * 60 * 60 * 1000; // 1 an
|
||||
case '2y':
|
||||
return 2 * 365 * 24 * 60 * 60 * 1000; // 2 ans
|
||||
case '3y':
|
||||
return 3 * 365 * 24 * 60 * 60 * 1000; // 3 ans
|
||||
default:
|
||||
return 90 * 24 * 60 * 60 * 1000; // Par défaut 90 jours
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Détermine si une PR est automatique (bot, renovate, dependabot, etc.)
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user