mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
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:
@@ -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'));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user