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
32 changes: 32 additions & 0 deletions .cursor/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
FROM ubuntu:24.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl \
git \
gnupg \
jq \
openssh-server \
software-properties-common \
sudo \
unzip \
&& rm -rf /var/lib/apt/lists/*

RUN add-apt-repository -y ppa:ondrej/php \
&& apt-get update && apt-get install -y --no-install-recommends \
php8.5-bcmath \
php8.5-cli \
php8.5-curl \
php8.5-intl \
php8.5-mbstring \
php8.5-mysql \
php8.5-sqlite3 \
php8.5-xml \
php8.5-zip \
&& rm -rf /var/lib/apt/lists/*

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

WORKDIR /home/ubuntu
15 changes: 15 additions & 0 deletions .cursor/cloud-agent-install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -euo pipefail

composer install --no-interaction

if [[ ! -f .env ]]; then
cp .env.example .env
php artisan key:generate --no-interaction
fi

if [[ ! -f database/database.sqlite ]]; then
touch database/database.sqlite
fi

php artisan migrate --no-interaction
15 changes: 15 additions & 0 deletions .cursor/environment.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"build": {
"dockerfile": "Dockerfile",
"context": ".."
},
"install": "bash .cursor/cloud-agent-install.sh",
"start": "php artisan serve --host=0.0.0.0 --port=8000",
"terminals": [
{
"name": "App",
"command": "php artisan serve --host=0.0.0.0 --port=8000",
"ports": [8000]
}
]
}
81 changes: 81 additions & 0 deletions .cursor/test-cloud-environment.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"

pass() {
echo "cloud-env-test: ok $*"
}

fail() {
echo "cloud-env-test: FAIL $*" >&2
exit 1
}

require_command() {
command -v "$1" >/dev/null 2>&1 || fail "missing command: $1"
}

require_php_extension() {
php -m | grep -qi "^$1$" || fail "missing php extension: $1"
}

echo "cloud-env-test: validating Cursor Cloud image prerequisites"

require_command php
require_command composer
require_command git
require_command sudo
require_command jq
require_command bash

php -v | grep -q 'PHP 8.5' || fail "expected PHP 8.5"

for extension in bcmath curl intl mbstring pdo_sqlite xml zip; do
require_php_extension "$extension"
done

[[ -d /etc/ssh/sshd_config.d ]] || fail "missing /etc/ssh/sshd_config.d (install openssh-server)"
[[ -d /etc/sudoers.d ]] || fail "missing /etc/sudoers.d (install sudo)"

jq empty .cursor/environment.json || fail "invalid .cursor/environment.json"
[[ -f .cursor/Dockerfile ]] || fail "missing .cursor/Dockerfile"
[[ -x .cursor/hooks/php-quality.sh ]] || fail "php-quality hook is not executable"

pass "image prerequisites"

echo "cloud-env-test: running cloud agent install"

bash .cursor/cloud-agent-install.sh

[[ -f vendor/autoload.php ]] || fail "composer dependencies were not installed"
[[ -x vendor/bin/pest ]] || fail "pest binary missing after install"
[[ -x vendor/bin/pint ]] || fail "pint binary missing after install"
[[ -x vendor/bin/phpstan ]] || fail "phpstan binary missing after install"
[[ -x vendor/bin/rector ]] || fail "rector binary missing after install"

php artisan --version >/dev/null || fail "artisan is not runnable"
[[ -f .env ]] || fail ".env was not created"
[[ -f database/database.sqlite ]] || fail "sqlite database file was not created"

pass "application install"

echo "cloud-env-test: running php-quality hook smoke test"

hook_input=$(
jq -n \
--arg file_path "app/Http/Controllers/ProfileController.php" \
--arg workspace_root "$ROOT" \
'{file_path: $file_path, workspace_roots: [$workspace_root]}'
)

echo "$hook_input" | bash .cursor/hooks/php-quality.sh

pass "php-quality hook"

echo "cloud-env-test: running pest suite"

php artisan test --compact

pass "all cloud environment checks passed"
35 changes: 35 additions & 0 deletions .github/workflows/cloud-environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Cloud environment

on:
pull_request:
paths:
- '.cursor/**'
- 'composer.json'
- 'composer.lock'
- '.github/workflows/cloud-environment.yml'
push:
branches:
- main
paths:
- '.cursor/**'
- 'composer.json'
- 'composer.lock'
- '.github/workflows/cloud-environment.yml'

permissions:
contents: read

jobs:
cloud_environment:
name: Cursor Cloud Docker image
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- name: Build Cursor Cloud image
run: docker build -f .cursor/Dockerfile -t kaper-dev-cloud .

- name: Validate cloud environment
run: docker run --rm -v "$PWD:/workspace" -w /workspace kaper-dev-cloud bash .cursor/test-cloud-environment.sh
6 changes: 5 additions & 1 deletion .github/workflows/composer-normalize.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: Composer Normalize

on: [push, pull_request]
on:
pull_request:
push:
branches:
- main

permissions:
contents: read
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/pest.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: Pest tests

on: [push, pull_request]
on:
pull_request:
push:
branches:
- main

permissions:
contents: read
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/phpstan.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: PHPStan

on: [push, pull_request]
on:
pull_request:
push:
branches:
- main

permissions:
contents: read
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/pint.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: Pint

on: [push, pull_request]
on:
pull_request:
push:
branches:
- main

permissions:
contents: read
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/rector.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: Rector

on: [push, pull_request]
on:
pull_request:
push:
branches:
- main

permissions:
contents: read
Expand Down