feat: remove CommitSkipPatterns - already available in 1.9.x

Keep only branch and path skip trigger logic. Commit message skip
is handled by the existing Contains(VCS_DEPLOYMENT_SKIP_PATTERNS) check.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
harsh mahajan
2026-05-19 11:21:04 +05:30
parent a4a57bc64d
commit 3b3a04877f
3 changed files with 0 additions and 322 deletions
-22
View File
@@ -863,17 +863,6 @@ return [
'array' => true,
'filters' => [],
],
[
'$id' => ID::custom('providerCommitSkipPatterns'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 128,
'signed' => true,
'required' => false,
'default' => [],
'array' => true,
'filters' => [],
],
],
'indexes' => [
[
@@ -1375,17 +1364,6 @@ return [
'array' => true,
'filters' => [],
],
[
'$id' => ID::custom('providerCommitSkipPatterns'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 128,
'signed' => true,
'required' => false,
'default' => [],
'array' => true,
'filters' => [],
],
],
'indexes' => [
[
@@ -1,85 +0,0 @@
<?php
namespace Appwrite\Vcs\Validator;
use Utopia\Validator;
class CommitSkipPatterns extends Validator
{
public function __construct(private readonly array $patterns)
{
}
/**
* Returns false (skip deployment) when the commit message contains any of the
* configured patterns as a standalone directive (case-insensitive).
* Returns true (proceed) when no patterns are configured or none match.
*
* Matching rules:
* - Case-insensitive
* - The directive must be surrounded by whitespace or string boundaries, so
* "prefix[skip deploy]suffix" does NOT accidentally skip
* - Internal whitespace in the pattern is normalised: tokens are split on \s+
* and rejoined with \s* in the regex, so "[skip deploy]" matches
* "[skip deploy]" and "skip-checks: true" matches "skip-checks:true"
*/
public function isValid($value): bool
{
if (!is_string($value)) {
return false;
}
foreach ($this->patterns as $pattern) {
if (!is_string($pattern)) {
continue;
}
$pattern = trim($pattern);
if ($pattern === '') {
continue;
}
// Split on whitespace; each token is regex-quoted. Tokens are rejoined
// with \s+ (required space) so that "skipappwrite" does NOT match the
// pattern "skip appwrite". The only exception: when the preceding token
// ends with ":" (git trailer style), \s* is used so that
// "skip-checks:true" still matches the pattern "skip-checks: true".
$tokens = preg_split('/\s+/', $pattern);
$regexParts = [];
$count = count($tokens);
for ($i = 0; $i < $count; $i++) {
$regexParts[] = preg_quote($tokens[$i], '~');
if ($i < $count - 1) {
$regexParts[] = str_ends_with($tokens[$i], ':') ? '\s*' : '\s+';
}
}
$regexBody = implode('', $regexParts);
// (?<!\S) / (?!\S) assert whitespace (or string edge) on both sides,
// ensuring the directive is a standalone group, not buried inside a
// longer token like "prefix[skip deploy]suffix".
$regex = '~(?<!\S)' . $regexBody . '(?!\S)~i';
if (preg_match($regex, $value)) {
return false;
}
}
return true;
}
public function getDescription(): string
{
return 'Commit message must not contain any of the configured skip patterns.';
}
public function isArray(): bool
{
return false;
}
public function getType(): string
{
return self::TYPE_STRING;
}
}
@@ -1,215 +0,0 @@
<?php
namespace Tests\Unit\Vcs\Validator;
use Appwrite\Vcs\Validator\CommitSkipPatterns;
use PHPUnit\Framework\TestCase;
class CommitSkipPatternsTest extends TestCase
{
// -------------------------------------------------------------------------
// Empty patterns — never skip
// -------------------------------------------------------------------------
public function testEmptyPatternsNeverSkip(): void
{
$validator = new CommitSkipPatterns([]);
$this->assertTrue($validator->isValid('fix: update readme'));
$this->assertTrue($validator->isValid('[skip deploy] docs only'));
$this->assertTrue($validator->isValid(''));
}
// -------------------------------------------------------------------------
// Single pattern — directive match
// -------------------------------------------------------------------------
public function testSinglePatternMatchSkips(): void
{
$validator = new CommitSkipPatterns(['[skip deploy]']);
$this->assertFalse($validator->isValid('[skip deploy] docs only'));
$this->assertFalse($validator->isValid('chore: update deps [skip deploy]'));
$this->assertFalse($validator->isValid('prefix [skip deploy] suffix'));
}
public function testSinglePatternNoMatchProceeds(): void
{
$validator = new CommitSkipPatterns(['[skip deploy]']);
$this->assertTrue($validator->isValid('fix: real bug fix'));
$this->assertTrue($validator->isValid('feat: add new feature'));
$this->assertTrue($validator->isValid('skip deploy without brackets'));
$this->assertTrue($validator->isValid('prefix[skip deploy]suffix'));
}
// -------------------------------------------------------------------------
// Case insensitivity
// -------------------------------------------------------------------------
public function testCaseInsensitiveMatch(): void
{
$validator = new CommitSkipPatterns(['[skip deploy]']);
$this->assertFalse($validator->isValid('[SKIP DEPLOY] uppercase'));
$this->assertFalse($validator->isValid('[Skip Deploy] mixed case'));
$this->assertFalse($validator->isValid('[skip DEPLOY] partial upper'));
}
public function testPatternItselfCaseInsensitive(): void
{
$validator = new CommitSkipPatterns(['[SKIP DEPLOY]']);
$this->assertFalse($validator->isValid('[skip deploy] lowercase message'));
$this->assertFalse($validator->isValid('[Skip Deploy] mixed message'));
}
// -------------------------------------------------------------------------
// Array of patterns — any match skips (OR semantics)
// -------------------------------------------------------------------------
public function testMultiplePatternsFirstMatches(): void
{
$validator = new CommitSkipPatterns(['[skip deploy]', '[skip ci]', '[no deploy]']);
$this->assertFalse($validator->isValid('[skip deploy] docs only'));
}
public function testMultiplePatternsSecondMatches(): void
{
$validator = new CommitSkipPatterns(['[skip deploy]', '[skip ci]', '[no deploy]']);
$this->assertFalse($validator->isValid('chore: update readme [skip ci]'));
}
public function testMultiplePatternsThirdMatches(): void
{
$validator = new CommitSkipPatterns(['[skip deploy]', '[skip ci]', '[no deploy]']);
$this->assertFalse($validator->isValid('[no deploy] just docs'));
}
public function testMultiplePatternsNoneMatchProceeds(): void
{
$validator = new CommitSkipPatterns(['[skip deploy]', '[skip ci]', '[no deploy]']);
$this->assertTrue($validator->isValid('feat: completely new feature'));
$this->assertTrue($validator->isValid('fix: important bug fix'));
}
// -------------------------------------------------------------------------
// Common real-world skip conventions
// -------------------------------------------------------------------------
public function testCommonSkipCiPattern(): void
{
$validator = new CommitSkipPatterns(['[skip ci]']);
$this->assertFalse($validator->isValid('[skip ci] update changelog'));
$this->assertFalse($validator->isValid('[SKIP CI]'));
$this->assertTrue($validator->isValid('feat: something real'));
}
public function testNoDeployPattern(): void
{
$validator = new CommitSkipPatterns(['[no deploy]']);
$this->assertFalse($validator->isValid('[no deploy] tweak docs'));
$this->assertTrue($validator->isValid('deploy this please'));
}
// -------------------------------------------------------------------------
// Edge cases
// -------------------------------------------------------------------------
public function testEmptyCommitMessageNeverSkipsWithPatterns(): void
{
$validator = new CommitSkipPatterns(['[skip deploy]']);
$this->assertTrue($validator->isValid(''));
}
public function testBlankPatternsInArrayAreIgnored(): void
{
$validator = new CommitSkipPatterns(['', ' ', '[skip deploy]']);
$this->assertTrue($validator->isValid('normal commit message'));
$this->assertFalse($validator->isValid('[skip deploy] docs'));
}
public function testPatternMustBeStandaloneDirective(): void
{
$validator = new CommitSkipPatterns(['[skip deploy]']);
$this->assertTrue($validator->isValid('skippy the kangaroo'));
$this->assertTrue($validator->isValid('prefix[skip deploy]suffix'));
}
public function testMultilineCommitMessage(): void
{
$validator = new CommitSkipPatterns(['[skip deploy]']);
$msg = "feat: add new stuff\n\nMore detail here.\n\n[skip deploy]";
$this->assertFalse($validator->isValid($msg));
}
public function testWhitespaceInsideDirectiveIsNormalized(): void
{
$validator = new CommitSkipPatterns([' [skip deploy] ']);
$this->assertFalse($validator->isValid('[skip deploy] docs only'));
$this->assertFalse($validator->isValid('[SKIP DEPLOY] docs only'));
}
public function testTrailerDirectiveCanSkip(): void
{
$validator = new CommitSkipPatterns(['skip-checks: true']);
$msg = "feat: add new stuff\n\nMore detail here.\n\nskip-checks:true";
$this->assertFalse($validator->isValid($msg));
}
// -------------------------------------------------------------------------
// Plain-word patterns: "skip appwrite" and "appwrite skip"
// -------------------------------------------------------------------------
public function testSkipAppwritePatternSkips(): void
{
$validator = new CommitSkipPatterns(['skip appwrite']);
$this->assertFalse($validator->isValid('docs: update readme skip appwrite'));
$this->assertFalse($validator->isValid('skip appwrite'));
}
public function testSkipAppwritePatternCaseInsensitive(): void
{
$validator = new CommitSkipPatterns(['skip appwrite']);
$this->assertFalse($validator->isValid('SKIP APPWRITE'));
$this->assertFalse($validator->isValid('Skip Appwrite'));
$this->assertFalse($validator->isValid('SKIP appwrite'));
}
public function testSkipAppwritePatternNoMatchProceeds(): void
{
$validator = new CommitSkipPatterns(['skip appwrite']);
$this->assertTrue($validator->isValid('feat: real feature'));
$this->assertTrue($validator->isValid('skipappwrite')); // no space — not standalone
$this->assertTrue($validator->isValid('appwrite is great'));
}
public function testAppwriteSkipPatternSkips(): void
{
$validator = new CommitSkipPatterns(['appwrite skip']);
$this->assertFalse($validator->isValid('appwrite skip ci'));
$this->assertFalse($validator->isValid('docs appwrite skip'));
$this->assertFalse($validator->isValid('appwrite skip'));
}
public function testAppwriteSkipPatternCaseInsensitive(): void
{
$validator = new CommitSkipPatterns(['appwrite skip']);
$this->assertFalse($validator->isValid('APPWRITE SKIP'));
$this->assertFalse($validator->isValid('Appwrite Skip'));
$this->assertFalse($validator->isValid('appwrite SKIP'));
}
public function testAppwriteSkipPatternNoMatchProceeds(): void
{
$validator = new CommitSkipPatterns(['appwrite skip']);
$this->assertTrue($validator->isValid('feat: deploy appwrite changes'));
$this->assertTrue($validator->isValid('appwriteskip')); // no space — not standalone
$this->assertTrue($validator->isValid('skip the appwrite stuff'));
}
public function testBothAppwritePatternsInArray(): void
{
$validator = new CommitSkipPatterns(['skip appwrite', 'appwrite skip']);
$this->assertFalse($validator->isValid('skip appwrite'));
$this->assertFalse($validator->isValid('appwrite skip'));
$this->assertFalse($validator->isValid('SKIP APPWRITE'));
$this->assertFalse($validator->isValid('APPWRITE SKIP'));
$this->assertTrue($validator->isValid('feat: deploy appwrite changes'));
}
}