Add GitHub publish script and bump version to 0.9-rc2

This commit is contained in:
root
2026-01-24 22:49:50 +02:00
parent 3986f0d089
commit f6402cffc4
9 changed files with 149 additions and 30 deletions

View File

@@ -59,22 +59,21 @@ php artisan route:cache # Cache routes
**Important:** Only push to git when explicitly requested by the user. Do not auto-push after commits.
### Version & Build Numbers
### Version Numbers
**IMPORTANT:** Before every push, bump the BUILD number in the `VERSION` file:
**IMPORTANT:** Before every push, bump the `VERSION` in the `VERSION` file:
```bash
# VERSION file format:
VERSION=1.0.3
BUILD=005
VERSION=0.9-rc
# Increment BUILD before pushing (e.g., 005 → 006)
# Bump before pushing:
# 0.9-rc → 0.9-rc1 → 0.9-rc2 → 0.9-rc3 → ...
```
| Field | When to Bump | Format |
|-------|--------------|--------|
| `VERSION` | Major releases, new features | Semantic versioning (X.Y.Z) |
| `BUILD` | Every push | Zero-padded number (001, 002, etc.) |
| `VERSION` | Every push | `0.9-rc`, `0.9-rc1`, `0.9-rc2`, ... |
## Test Server

View File

@@ -5,7 +5,7 @@
A modern web hosting control panel for WordPress and general PHP hosting. Built with Laravel 12, Filament v5, Livewire 4, and Tailwind CSS v4.
Version: 0.9-rc1 (release candidate)
Version: 0.9-rc2 (release candidate)
This is a release candidate. Expect rapid iteration and breaking changes until 1.0.

View File

@@ -1 +1 @@
VERSION=0.9-rc1
VERSION=0.9-rc2

View File

@@ -4,41 +4,86 @@ declare(strict_types=1);
namespace App\Filament\Jabali\Pages\Auth;
use App\Models\User;
use DanHarrin\LivewireRateLimiting\Exceptions\TooManyRequestsException;
use Filament\Auth\Http\Responses\Contracts\LoginResponse;
use Filament\Auth\MultiFactor\Contracts\HasBeforeChallengeHook;
use Filament\Auth\Pages\Login as BaseLogin;
use Filament\Facades\Filament;
use Filament\Models\Contracts\FilamentUser;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Support\Facades\Auth;
class Login extends BaseLogin
{
public function authenticate(): ?LoginResponse
{
$panel = Filament::getPanel('jabali');
Filament::setCurrentPanel($panel);
try {
$this->rateLimit(5);
} catch (TooManyRequestsException $exception) {
$this->getRateLimitedNotification($exception)?->send();
return null;
}
$data = $this->form->getState();
// Check credentials without logging in
$user = User::where('email', $data['email'])->first();
/** @var Guard $authGuard */
$authGuard = Auth::guard($panel->getAuthGuard());
$authProvider = $authGuard->getProvider();
$credentials = $this->getCredentialsFromFormData($data);
if ($user && \Hash::check($data['password'], $user->password)) {
// Check if 2FA is enabled
if ($user->two_factor_secret && $user->two_factor_confirmed_at) {
// Store user ID in session for 2FA challenge
session(['login.id' => $user->id]);
session(['login.remember' => $data['remember'] ?? false]);
$user = $authProvider->retrieveByCredentials($credentials);
if ((! $user) || (! $authProvider->validateCredentials($user, $credentials))) {
$this->userUndertakingMultiFactorAuthentication = null;
$this->fireFailedEvent($authGuard, $user, $credentials);
$this->throwFailureValidationException();
}
if (
filled($this->userUndertakingMultiFactorAuthentication) &&
(decrypt($this->userUndertakingMultiFactorAuthentication) === $user->getAuthIdentifier())
) {
$this->multiFactorChallengeForm->validate();
} else {
foreach (Filament::getMultiFactorAuthenticationProviders() as $multiFactorAuthenticationProvider) {
if (! $multiFactorAuthenticationProvider->isEnabled($user)) {
continue;
}
$this->userUndertakingMultiFactorAuthentication = encrypt($user->getAuthIdentifier());
if ($multiFactorAuthenticationProvider instanceof HasBeforeChallengeHook) {
$multiFactorAuthenticationProvider->beforeChallenge($user);
}
break;
}
if (filled($this->userUndertakingMultiFactorAuthentication)) {
$this->multiFactorChallengeForm->fill();
// Redirect to 2FA challenge
$this->redirect(route('filament.jabali.auth.two-factor-challenge'));
return null;
}
}
$response = parent::authenticate();
if ($user instanceof FilamentUser && ! $user->canAccessPanel($panel)) {
$this->fireFailedEvent($authGuard, $user, $credentials);
$this->throwFailureValidationException();
}
$authGuard->login($user, $data['remember'] ?? false);
session()->regenerate();
// If authentication successful, check if user is admin
$user = Filament::auth()->user();
$user = $authGuard->user();
if ($user && $user->is_admin) {
// Log out from user panel guard
Filament::auth()->logout();
$authGuard->logout();
// Redirect admins to admin panel using Livewire's redirect
$this->redirect(route('filament.admin.pages.dashboard'));
@@ -46,6 +91,6 @@ class Login extends BaseLogin
return null;
}
return $response;
return app(LoginResponse::class);
}
}

View File

@@ -1092,7 +1092,7 @@ server {
location ~ \.php$ {
fastcgi_pass unix:SOCKET_PLACEHOLDER;
fastcgi_next_upstream error timeout invalid_header http_500 http_503 http_504;
fastcgi_next_upstream error timeout invalid_header http_500 http_503;
fastcgi_next_upstream_tries 2;
fastcgi_next_upstream_timeout 5s;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
@@ -6929,7 +6929,7 @@ server {
location ~ \.php\$ {
fastcgi_pass unix:/var/run/php/php8.4-fpm-{$username}.sock;
fastcgi_next_upstream error timeout invalid_header http_500 http_503 http_504;
fastcgi_next_upstream error timeout invalid_header http_500 http_503;
fastcgi_next_upstream_tries 2;
fastcgi_next_upstream_timeout 5s;
fastcgi_index index.php;
@@ -11714,7 +11714,7 @@ server {
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.4-fpm-$username.sock;
fastcgi_next_upstream error timeout invalid_header http_500 http_503 http_504;
fastcgi_next_upstream error timeout invalid_header http_500 http_503;
fastcgi_next_upstream_tries 2;
fastcgi_next_upstream_timeout 5s;
fastcgi_param SCRIPT_FILENAME \$realpath_root\$fastcgi_script_name;

50
bin/publish-github Executable file
View File

@@ -0,0 +1,50 @@
#!/usr/bin/env bash
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$repo_root"
remote_name="github"
source_branch="main"
publish_branch="github-main"
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "Not a git repository." >&2
exit 1
fi
if ! git remote get-url "$remote_name" >/dev/null 2>&1; then
echo "Remote '$remote_name' is not configured." >&2
exit 1
fi
if ! git diff --quiet || ! git diff --cached --quiet; then
echo "Working tree is not clean. Commit or stash changes first." >&2
exit 1
fi
original_branch="$(git rev-parse --abbrev-ref HEAD)"
if [[ "$original_branch" != "$source_branch" && "$original_branch" != "$publish_branch" ]]; then
echo "Switch to '$source_branch' or '$publish_branch' before publishing." >&2
exit 1
fi
if git fetch "$remote_name" --quiet; then
current_version="$(grep -E '^VERSION=' VERSION | head -n1 | cut -d= -f2-)"
remote_version="$(git show "$remote_name/main:VERSION" 2>/dev/null | grep -E '^VERSION=' | head -n1 | cut -d= -f2- || true)"
if [[ -n "$remote_version" && "$current_version" == "$remote_version" ]]; then
echo "VERSION unchanged vs GitHub ($current_version). Bump VERSION before pushing." >&2
exit 1
fi
fi
git checkout -B "$publish_branch" "$source_branch"
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch CLAUDE.md" \
--prune-empty --tag-name-filter cat -- "$publish_branch"
git push "$remote_name" "$publish_branch:main" --force
git checkout "$original_branch"

View File

@@ -12,7 +12,7 @@
set -e
# Version - will be read from VERSION file after clone, this is fallback
JABALI_VERSION="0.9-rc"
JABALI_VERSION="0.9-rc2"
# Colors
RED='\033[0;31m'

View File

@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace Tests\Unit;
use PHPUnit\Framework\TestCase;
class PublishGithubScriptTest extends TestCase
{
public function test_publish_github_script_exists_and_protects_claude(): void
{
$scriptPath = dirname(__DIR__, 2).'/bin/publish-github';
$this->assertFileExists($scriptPath);
$this->assertTrue(is_executable($scriptPath));
$content = file_get_contents($scriptPath);
$this->assertNotFalse($content);
$this->assertStringContainsString('CLAUDE.md', $content);
$this->assertStringContainsString('github-main', $content);
$this->assertStringContainsString('github', $content);
}
}

View File

@@ -14,7 +14,7 @@ class VersionFileTest extends TestCase
$content = file_get_contents($versionPath);
$this->assertNotFalse($content);
$this->assertStringContainsString('VERSION=0.9-rc1', $content);
$this->assertStringContainsString('VERSION=0.9-rc2', $content);
$this->assertStringNotContainsString('BUILD=', $content);
}
}