Skip to content
Merged
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
16 changes: 13 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,19 @@ jobs:
coverage: none
- name: Composer install
run: composer install --prefer-dist --no-interaction --no-progress
# Without `|| true`. Every one of these swallowed its exit code, so this
# job reported success whatever happened — the only check in the repository
# that could not fail, sitting next to a Tests workflow that could not
# pass. Neither told anyone anything.
#
# Pest is scoped to the gate suites for the same reason tests.yml is: the
# Module suite is tracked debt, reported by its own non-gating job.
- name: Pint
run: vendor/bin/pint --test || true
run: vendor/bin/pint --test
- name: PHPStan
run: vendor/bin/phpstan analyse --no-progress || true
run: vendor/bin/phpstan analyse --no-progress
# No --no-interaction: that is a PHPUnit flag, and Pest rejects it with
# `Unknown option` and exit 2. The `|| true` had been hiding a broken
# invocation, not merely failing tests — this step has never run the suite.
- name: Pest
run: vendor/bin/pest --no-coverage --no-interaction || true
run: vendor/bin/pest --testsuite=Feature,Unit --no-coverage
50 changes: 48 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ jobs:
runs-on: ubuntu-latest

strategy:
fail-fast: true
# One leg failing should not hide the others. With fail-fast the first
# failure cancels the rest, so a PHP-version-specific break looks
# identical to a break on every version.
fail-fast: false
matrix:
php: [8.2, 8.3, 8.4]
laravel: [12.*]
Expand All @@ -36,8 +39,14 @@ jobs:
composer require "laravel/framework:${LARAVEL_VERSION}" --no-interaction --no-update
composer update --prefer-dist --no-interaction --no-progress

# The gate suites only. A bare `phpunit` also runs the Module suite —
# src/**/*Test.php — which carries known failures and is treated as
# visible debt rather than a gate (see .gitlab-ci.yml's module-suite-debt
# job, and the module-debt job below). Including it here meant this
# workflow could never be green, so it stopped meaning anything: the same
# rot as a check that always passes, arrived at from the other side.
- name: Execute tests with coverage
run: vendor/bin/phpunit --coverage-clover=coverage.xml
run: vendor/bin/phpunit --testsuite=Feature,Unit --coverage-clover=coverage.xml

- name: Upload coverage to Codecov
if: matrix.php == '8.3'
Expand All @@ -46,3 +55,40 @@ jobs:
files: ./coverage.xml
fail_ci_if_error: false
verbose: true

# The Module suite — src/**/*Test.php — reported, never gating.
#
# It carries known failures, and the number is worth seeing rather than
# hiding: 448 at the time of writing, and they are not 448 bugs. Roughly 114
# are class-not-found for classes owned by sibling packages (Core\Tenant\Models,
# Core\Agentic\Services) — tests that cannot pass in this repository at all;
# about 30 are one real defect, StorageUrlResolver being handed a CdnUrlBuilder
# where it wants a BunnyStorageService; the rest are ordinary assertion and
# status-code failures.
#
# continue-on-error rather than `|| true`, and the difference matters: this
# way the step's own result is visible in the run, so the count can be driven
# down. A step that swallows its exit code teaches nobody anything.
#
# When it reaches zero, fold --testsuite=Module into the job above and delete
# this one. Mirrors .gitlab-ci.yml's module-suite-debt job.
module-debt:
runs-on: ubuntu-latest
name: Module suite (reported, not gating)
continue-on-error: true
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
extensions: dom, curl, libxml, mbstring, zip
coverage: none

- name: Install dependencies
run: composer install --prefer-dist --no-interaction --no-progress

- name: Execute the Module suite
run: vendor/bin/phpunit --testsuite=Module
2 changes: 1 addition & 1 deletion src/Core/Cdn/Models/StorageOffload.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ public function scopeForDisk($query, string $disk)
/**
* Get human-readable file size.
*/
public function getFileSizeHumanAttribute(): string
protected function getFileSizeHumanAttribute(): string
{
$bytes = $this->file_size ?? 0;
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
Expand Down
4 changes: 2 additions & 2 deletions src/Core/Config/Models/ConfigValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class ConfigValue extends Model
/**
* Get the value attribute with automatic decryption for sensitive keys.
*/
public function getValueAttribute(mixed $value): mixed
protected function getValueAttribute(mixed $value): mixed
{
if ($value === null) {
return null;
Expand All @@ -91,7 +91,7 @@ public function getValueAttribute(mixed $value): mixed
/**
* Set the value attribute with automatic encryption for sensitive keys.
*/
public function setValueAttribute(mixed $value): void
protected function setValueAttribute(mixed $value): void
{
// Check if the key is sensitive (need to load it if not already)
$key = $this->relationLoaded('key')
Expand Down
4 changes: 2 additions & 2 deletions src/Core/Media/Image/ImageOptimization.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public function scopeForWorkspace($query, ?Model $workspace)
*
* Example: "45% saved (120KB → 66KB)"
*/
public function getSavingsHumanAttribute(): string
protected function getSavingsHumanAttribute(): string
{
// Format with appropriate unit
$original = $this->formatBytes($this->original_size);
Expand All @@ -117,7 +117,7 @@ public function getSavingsHumanAttribute(): string
/**
* Get human-readable size saved.
*/
public function getSizeSavedHumanAttribute(): string
protected function getSizeSavedHumanAttribute(): string
{
$saved = $this->original_size - $this->optimized_size;

Expand Down
4 changes: 2 additions & 2 deletions src/Core/Seo/Models/SeoScoreHistory.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public function seoMetadata(): BelongsTo
/**
* Get the score color for UI display.
*/
public function getScoreColorAttribute(): string
protected function getScoreColorAttribute(): string
{
return match (true) {
$this->score >= 80 => 'green',
Expand All @@ -120,7 +120,7 @@ public function getScoreColorAttribute(): string
/**
* Get the issue count.
*/
public function getIssueCountAttribute(): int
protected function getIssueCountAttribute(): int
{
return count($this->issues ?? []);
}
Expand Down
12 changes: 6 additions & 6 deletions src/Core/Seo/SeoMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class SeoMetadata extends Model
*
* @return array<string, mixed>|null
*/
public function getSchemaMarkupAttribute(): ?array
protected function getSchemaMarkupAttribute(): ?array
{
if ($this->schemaMarkupLoaded) {
return $this->parsedSchemaMarkup;
Expand Down Expand Up @@ -132,7 +132,7 @@ public function getSchemaMarkupAttribute(): ?array
*
* @param array<string, mixed>|string|null $value
*/
public function setSchemaMarkupAttribute(array|string|null $value): void
protected function setSchemaMarkupAttribute(array|string|null $value): void
{
// Reset the lazy loading cache
$this->parsedSchemaMarkup = null;
Expand Down Expand Up @@ -183,7 +183,7 @@ public function seoable(): MorphTo
*
* Uses JSON_HEX_TAG to prevent XSS via </script> in content.
*/
public function getJsonLdAttribute(): string
protected function getJsonLdAttribute(): string
{
if (empty($this->schema_markup)) {
return '';
Expand All @@ -197,7 +197,7 @@ public function getJsonLdAttribute(): string
/**
* Generate all meta tags as HTML.
*/
public function getMetaTagsAttribute(): string
protected function getMetaTagsAttribute(): string
{
$tags = [];

Expand Down Expand Up @@ -241,7 +241,7 @@ public function getMetaTagsAttribute(): string
/**
* Get SEO score colour for UI display.
*/
public function getScoreColorAttribute(): string
protected function getScoreColorAttribute(): string
{
if ($this->seo_score === null) {
return 'zinc';
Expand All @@ -265,7 +265,7 @@ public function hasIssues(): bool
/**
* Get the count of issues.
*/
public function getIssueCountAttribute(): int
protected function getIssueCountAttribute(): int
{
return count($this->seo_issues ?? []);
}
Expand Down
Loading