From 879c95f744a30082f6eea420f56f20086bd09820 Mon Sep 17 00:00:00 2001 From: SukkaW Date: Sat, 1 Aug 2026 13:23:50 +0800 Subject: [PATCH] Chore: short circut output content hash comparision on CI --- Build/lib/writing-strategy/base.ts | 21 ++++++++++++++++++++- Build/lib/writing-strategy/singbox.ts | 3 +++ Build/lib/writing-strategy/surge.ts | 3 +++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Build/lib/writing-strategy/base.ts b/Build/lib/writing-strategy/base.ts index 856a98e0..d6e4503a 100644 --- a/Build/lib/writing-strategy/base.ts +++ b/Build/lib/writing-strategy/base.ts @@ -1,6 +1,7 @@ +import { isCI } from 'ci-info'; import type { Span } from '../../trace'; import { calculateContentHash } from '../content-hash'; -import { compareAndWriteFile } from '../create-file'; +import { compareAndWriteFile, writeFileLines } from '../create-file'; /** * The class is not about holding rule data, instead it determines how the @@ -27,6 +28,14 @@ export abstract class BaseWriteStrategy { protected abstract result: string[] | null; + /** + * Whether the output has no volatile metadata (e.g. "Last Updated") to preserve, + * so on CI the previous file can simply be overwritten without comparison (the + * comparison would only serve to reduce SSD wear, which CI doesn't care about). + * Only enable this when withPadding emits neither a banner nor any date. + */ + protected readonly skipCompareOnCI: boolean = false; + abstract writeDomain(domain: string): void; abstract writeDomainSuffix(domain: string): void; abstract writeDomainKeywords(keyword: Set): void; @@ -59,6 +68,16 @@ export abstract class BaseWriteStrategy { return; } + // Without volatile metadata to preserve, the compare-before-write only serves + // to reduce SSD wear -- irrelevant on CI, so skip hashing and comparison alike. + if (isCI && this.skipCompareOnCI) { + return writeFileLines( + span, + this.withPadding(title, description, date, result, null), + filePath + ); + } + // The hash covers the real content (title, description and rules) but not the // volatile date, so compareAndWriteFile can bail out by only reading the head // of the previous output. Strategies whose withPadding doesn't embed the marker diff --git a/Build/lib/writing-strategy/singbox.ts b/Build/lib/writing-strategy/singbox.ts index 7aab5ce5..7acb947a 100644 --- a/Build/lib/writing-strategy/singbox.ts +++ b/Build/lib/writing-strategy/singbox.ts @@ -34,6 +34,9 @@ export class SingboxSource extends BaseWriteStrategy { static readonly jsonToLines = (json: unknown): string[] => stringify(json).split('\n'); + // JSON output has no metadata comment at all, nothing to preserve + protected override readonly skipCompareOnCI = true; + private readonly singbox: SingboxHeadlessRule = { domain: [MARKER_DOMAIN], domain_suffix: [MARKER_DOMAIN] diff --git a/Build/lib/writing-strategy/surge.ts b/Build/lib/writing-strategy/surge.ts index 767013a1..f19c538c 100644 --- a/Build/lib/writing-strategy/surge.ts +++ b/Build/lib/writing-strategy/surge.ts @@ -154,6 +154,9 @@ export class SurgeMitmSgmodule extends BaseWriteStrategy { private readonly rules = new Set(); + // #!desc only carries a size derived from the rules, no volatile date + protected override readonly skipCompareOnCI = true; + protected get result() { if (this.rules.size === 0) { return null;