Skip to content
Closed
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
143 changes: 82 additions & 61 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,147 +1,163 @@
version: 2.1

jobs:
build:
machine:
image: ubuntu-2204:current
resource_class: large
environment:
- TZ: "UTC"

# Shared setup steps via CircleCI reusable command.
# Both jobs need their own Docker environment (CircleCI jobs can't share Docker).
commands:
setup_docker:
steps:
- checkout

# Install Task

- run:
name: Install Task
command: |
sudo sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin
task --version

# Set up environment file
- run:
name: Setup environment
command: |
cp .env.example .env

# Configure for Docker Compose setup
sed -i 's/DB_HOST=.*$/DB_HOST=restarters_db/g' .env
sed -i 's/DB_DATABASE=.*$/DB_DATABASE=restarters_db_test/g' .env
sed -i 's/DB_USERNAME=.*$/DB_USERNAME=restarters/g' .env
sed -i 's/DB_PASSWORD=.*$/DB_PASSWORD=s3cr3t/g' .env

# Configure Discourse integration
sed -i 's/FEATURE__DISCOURSE_INTEGRATION=.*$/FEATURE__DISCOURSE_INTEGRATION=true/g' .env
sed -i 's/DISCOURSE_URL=.*$/DISCOURSE_URL=http:\/\/restarters_discourse/g' .env
sed -i 's/DISCOURSE_APIKEY=.*$/DISCOURSE_APIKEY=fb71f38ca2b8b7cd6a041e57fd8202c9937088f0ecae7db40722bd758dda92fc/g' .env
sed -i 's/DISCOURSE_APIUSER=.*$/DISCOURSE_APIUSER=someuser/g' .env

# Configure for testing
sed -i 's/APP_DEBUG=.*$/APP_DEBUG=false/g' .env
sed -i 's/SESSION_DOMAIN=.*$/SESSION_DOMAIN=localhost/g' .env
sed -i 's/HONEYPOT_DISABLE=.*$/HONEYPOT_DISABLE=TRUE/g' .env
sed -i 's/APP_URL=.*$/APP_URL=http:\/\/localhost:8001/g' .env

# Add environment variables from CircleCI
echo "" >> .env
echo "GOOGLE_API_CONSOLE_KEY=$GOOGLE_API_CONSOLE_KEY" >> .env
echo "MAPBOX_TOKEN=$MAPBOX_TOKEN" >> .env

# Start Docker services using Task
- restore_cache:
keys:
- composer-v2-{{ checksum "composer.lock" }}
- composer-v2-

- restore_cache:
keys:
- node-modules-v1-{{ checksum "package-lock.json" }}
- node-modules-v1-

- run:
name: Build frontend assets
command: |
npm install --legacy-peer-deps
npm run build
no_output_timeout: 15m

- save_cache:
key: node-modules-v1-{{ checksum "package-lock.json" }}
paths:
- node_modules

- run:
name: Start Docker services
command: |
# Set environment variable for CircleCI detection
export CIRCLECI=true
# Enable Docker Compose bake for build optimization
export COMPOSE_BAKE=true
# Start all services using Task
task docker:up-all
no_output_timeout: 10m

# Wait for services to be ready (includes build completion and restart detection)
- run:
name: Wait for services
command: |
task docker:wait-for-services-all

# Setup database and application
- save_cache:
key: composer-v2-{{ checksum "composer.lock" }}
paths:
- vendor

- run:
name: Setup application
command: |
# Grant timezone access - run directly on MySQL container
docker exec restarters_db mysql -u root -ps3cr3t -e "GRANT SELECT ON mysql.time_zone_name TO 'restarters'@'%';"

# Setup additional configuration needed for CI (most setup already done by docker_run.sh)
# Set MySQL function creators using session variable (compatible with MySQL 5.7)
docker exec restarters_db mysql -u root -ps3cr3t -e "SET GLOBAL log_bin_trust_function_creators = 1;"

# Disable ONLY_FULL_GROUP_BY for compatibility with getItemTypes() query
docker exec restarters_db mysql -u root -ps3cr3t -e "SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));"

# Generate additional Laravel artifacts for testing
docker exec restarters php artisan l5-swagger:generate

# Setup Discourse API
- run:
name: Setup Discourse
command: |
# Add API key to Discourse - run directly on PostgreSQL container
docker exec postgresql psql -U postgres -c "INSERT INTO api_keys (id, user_id, created_by_id, created_at, updated_at, allowed_ips, hidden, last_used_at, revoked_at, description, key_hash, truncated_key) VALUES (1, NULL, 1, '2021-10-25 13:56:20.033338', '2021-10-25 13:56:20.033338', NULL, false, NULL, NULL, 'Restarters', 'd89e9dfacfb611fbaf004807648187ce7ed474df44dcb0ada230fab5c8dd6a5b', '9fd7');" bitnami_discourse

# Configure Discourse settings
docker exec restarters php artisan discourse:setting personal_message_enabled_groups 10

# Run PHPUnit tests
jobs:
test-php:
machine:
image: ubuntu-2204:current
resource_class: large
environment:
- TZ: "UTC"

steps:
- setup_docker

- run:
name: Run PHPUnit tests
command: |
# Run PHPUnit tests using Task for consistency with local development
mkdir -p /tmp/test-results/phpunit
task docker:test:phpunit
# Copy test results to host
docker cp restarters:/tmp/phpunit-results.xml /tmp/test-results/phpunit/results.xml
no_output_timeout: 45m

# Run Jest tests
- run:
name: Run Jest tests
command: |
# Run Jest tests using Task for consistency with local development
mkdir -p /tmp/test-results/jest
task docker:test:jest
# Copy test results to host if they exist
docker cp restarters:/tmp/test-results/junit.xml /tmp/test-results/jest/junit.xml || echo "Jest results not found, skipping"

# Run main Playwright tests (excluding autocomplete)
- store_artifacts:
path: /tmp/test-results
destination: test-results-php

- store_test_results:
path: /tmp/test-results

test-playwright:
machine:
image: ubuntu-2204:current
resource_class: large
environment:
- TZ: "UTC"

steps:
- setup_docker

- run:
name: Run main Playwright tests
command: |
# Run Playwright tests using Task for consistency with local development
mkdir -p /tmp/test-results/playwright /tmp/test-results/logs
( while true; do sleep 60; echo "[ci-keepalive] $(date -u +%H:%M:%S)"; done ) &
KEEPALIVE_PID=$!
trap "kill $KEEPALIVE_PID 2>/dev/null || true" EXIT
task docker:test:playwright
no_output_timeout: 10m
EXIT_CODE=$?
kill $KEEPALIVE_PID 2>/dev/null || true
exit $EXIT_CODE
no_output_timeout: 30m

# Copy test results and artifacts
- run:
name: Copy Playwright artifacts
command: |
# Create test results directory on host
mkdir -p /tmp/test-results/playwright
mkdir -p /tmp/test-results/logs

# List what's available in the playwright container
mkdir -p /tmp/test-results/playwright /tmp/test-results/logs
docker exec restarters_playwright bash -c "ls -la /tmp/test-results/* || echo 'No playwright directories found'"

# Copy test results and artifacts from playwright container to host
docker cp restarters_playwright:/tmp/test-results/. /tmp/test-results/playwright/ || echo "Playwright HTML report not found"

# Copy Vite log from restarters container for debugging
docker cp restarters_playwright:/tmp/test-results/. /tmp/test-results/playwright/ || echo "Playwright results not found"
docker cp restarters:/tmp/vite.log /tmp/test-results/logs/vite.log || echo "Vite log not found"
docker logs restarters > /tmp/test-results/logs/restarters.log 2>&1 || echo "Could not capture restarters logs"
docker exec restarters bash -c "tail -300 /var/www/storage/logs/laravel.log 2>/dev/null" > /tmp/test-results/logs/laravel.log || echo "No laravel log found"
when: always

# Store artifacts
- store_artifacts:
path: /tmp/test-results
destination: playwright-test-results

- store_test_results:
path: /tmp/test-results

Expand Down Expand Up @@ -182,13 +198,18 @@ jobs:
workflows:
build-and-deploy:
jobs:
- build:
- test-php:
filters:
branches:
ignore: production
- test-playwright:
filters:
branches:
ignore: production
- deploy-fly-dev:
requires:
- build
- test-php
- test-playwright
filters:
branches:
only: develop
Expand Down
10 changes: 7 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# This is the docker for restarters. It's used from docker-compose.
FROM php:8.2-fpm
FROM php:8.4-fpm

# Install dependencies
RUN apt-get update && \
Expand All @@ -22,11 +22,15 @@
npx playwright install-deps && \
npm uninstall -g @playwright/test

ADD --chmod=0755 https://github.com/mlocati/docker-php-extension-installer/releases/download/2.7.31/install-php-extensions /usr/local/bin/
ADD --chmod=0755 https://github.com/mlocati/docker-php-extension-installer/releases/download/2.11.1/install-php-extensions /usr/local/bin/

# bcmath via PHP's own docker-php-ext-install — install-php-extensions
# trips over a pre-existing libbcmath/src/.libs directory in some PHP 8.4
# base image variants ("mkdir: cannot create directory ...: File exists").
RUN docker-php-ext-install bcmath

Check warning on line 30 in Dockerfile

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Merge this RUN instruction with the consecutive ones.

See more on https://sonarcloud.io/project/issues?id=TheRestartProject_restarters.net&issues=AZ6xjhRcqfj3Zztm5gAZ&open=AZ6xjhRcqfj3Zztm5gAZ&pullRequest=872

RUN install-php-extensions \
pdo_mysql \
bcmath \
zip \
xmlrpc \
xdebug \
Expand Down
8 changes: 5 additions & 3 deletions Dockerfile.fly
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# =============================================================================
# Stage 1: Build assets (Node + Composer)
# =============================================================================
FROM php:8.2-cli AS builder
FROM php:8.4-cli AS builder

# Install system dependencies for building
RUN apt-get update && apt-get install -y --no-install-recommends \
Expand All @@ -16,6 +16,7 @@ RUN pecl install channel://pecl.php.net/xmlrpc-1.0.0RC3 && docker-php-ext-enable

# Install composer
COPY --from=composer/composer:2-bin /composer /usr/bin/composer
ENV COMPOSER_ALLOW_SUPERUSER=1

# Install Node 18
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \
Expand All @@ -24,8 +25,9 @@ RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \

WORKDIR /build

# Copy composer files first for layer caching
# Copy composer files and patches for layer caching
COPY composer.json composer.lock ./
COPY patches/ ./patches/
RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist

# Copy package files for npm layer caching
Expand Down Expand Up @@ -62,7 +64,7 @@ RUN rm -f .env
# =============================================================================
# Stage 2: Production image (Nginx + PHP-FPM + Supervisord + Cron)
# =============================================================================
FROM php:8.2-fpm
FROM php:8.4-fpm

# yesterday mode adds mariadb-server (co-located DB for restored snapshots).
ARG STARTUP_SCRIPT=startup.sh
Expand Down
15 changes: 9 additions & 6 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ tasks:
else
echo "Running on CircleCI - skipping database reset (handled by CI setup)"
fi
- docker exec -e COVERALLS_REPO_TOKEN="$COVERALLS_REPO_TOKEN" restarters bash -c "export XDEBUG_MODE=coverage; ./vendor/bin/phpunit -d memory_limit=1024M --bootstrap vendor/autoload.php --coverage-clover tests/clover.xml --log-junit /tmp/phpunit-results.xml --configuration ./phpunit.xml --teamcity {{ .CLI_ARGS }}"
- docker exec -e COVERALLS_REPO_TOKEN="$COVERALLS_REPO_TOKEN" restarters bash -c "export XDEBUG_MODE=coverage; ./vendor/bin/phpunit -d memory_limit=1024M --bootstrap tests/bootstrap.php --coverage-clover tests/clover.xml --log-junit /tmp/phpunit-results.xml --configuration ./phpunit.xml --teamcity {{ .CLI_ARGS }}"
- |
if [ ! -z "$COVERALLS_REPO_TOKEN" ]; then
echo "Uploading coverage to Coveralls..."
Expand Down Expand Up @@ -264,13 +264,17 @@ tasks:
# Create test data for group tags tests (NC user, host user, network, group)
docker exec restarters php artisan tinker --execute='$nc = App\User::firstOrCreate(["email"=>"nc@test.net"], ["name"=>"NC User","password"=>Hash::make("passw0rd"),"consent_past_data"=>"2021-01-01","consent_future_data"=>"2021-01-01","consent_gdpr"=>"2021-01-01"]); $nc->role=6; $nc->save(); $host = App\User::firstOrCreate(["email"=>"host@test.net"], ["name"=>"Host User","password"=>Hash::make("passw0rd"),"consent_past_data"=>"2021-01-01","consent_future_data"=>"2021-01-01","consent_gdpr"=>"2021-01-01"]); $host->role=3; $host->save(); $network = App\Network::where("name","Test London")->first(); if (!$network) { $network = new App\Network(); $network->name="Test London"; $network->shortname="testlondon"; $network->description="Test network"; $network->default_language="en"; $network->save(); } DB::table("user_network")->insertOrIgnore(["user_id"=>$nc->id,"network_id"=>$network->id]); $group = App\Group::firstOrCreate(["name"=>"Tag Test Group"], ["website"=>"https://test.example.com","location"=>"London","area"=>"London","postcode"=>"SW1A 1AA","latitude"=>51.5,"longitude"=>-0.1,"free_text"=>"Test group","approved"=>true]); DB::table("group_network")->insertOrIgnore(["group_id"=>$group->idgroups,"network_id"=>$network->id]); DB::table("users_groups")->insertOrIgnore(["user"=>$host->id,"group"=>$group->idgroups,"role"=>3,"status"=>1]); echo "Group tags test data: NC=".$nc->id." Host=".$host->id." Network=".$network->id." Group=".$group->idgroups;' || true
- docker exec restarters bash -c "sed -i 's/.throttle:api.,//g' /var/www/app/Http/Kernel.php"
- |
# Stop Vite dev server BEFORE modifying .env.
# Vite v4 crashes with ERR_INVALID_ARG_TYPE when it detects .env changes mid-run;
# killing it first prevents the crash from corrupting the build environment.
echo "Stopping Vite dev server..."
docker exec restarters bash -c "ps aux | grep 'node.*vite' | grep -v grep | awk '{print \$2}' | xargs -r kill -9 || true"
- docker exec restarters bash -c "sed -i 's/APP_DEBUG=.*$/APP_DEBUG=false/g' /var/www/.env"
- docker exec restarters bash -c "sed -i 's/QUEUE_CONNECTION=.*/QUEUE_CONNECTION=sync/g' /var/www/.env"
- docker exec restarters bash -c "sed -i 's/MAIL_MAILER=.*/MAIL_MAILER=log/g' /var/www/.env"
- |
# Stop Vite dev server and build assets for production
echo "Stopping Vite dev server and building assets..."
docker exec restarters bash -c "ps aux | grep 'node.*vite' | grep -v grep | awk '{print \$2}' | xargs -r kill || true"
echo "Building assets for production..."
docker exec restarters bash -c "rm -f /var/www/public/hot && npm run build"
- |
# Ensure Playwright browsers are installed (handles version mismatches)
Expand All @@ -281,11 +285,10 @@ tasks:
export PLAYWRIGHT_TEST=true
export PLAYWRIGHT_DEBUG=true
export PWTEST_SKIP_TEST_OUTPUT=0
export DEBUG=playwright
export PLAYWRIGHT_BASE_URL=http://restarters_nginx
export PW_TEST_HTML_REPORT_OPEN=never
export FORCE_COLOR=1
stdbuf -oL -eL npx playwright test --reporter=html
stdbuf -oL -eL npx playwright test --reporter=list,html
"

docker:wait-for-services-*:
Expand Down
6 changes: 5 additions & 1 deletion app/Device.php
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,11 @@ public function uWasteDiverted()
{
$wasteDiverted = 0;

if ($this->isFixed() && $this->deviceCategory->isUnpowered()) {
$unpowered = \Cache::remember('category-unpowered-' . $this->category, 60, function() {
return $this->deviceCategory->isUnpowered();
});

if ($this->isFixed() && $unpowered) {
if ($this->estimate > 0) {
$wasteDiverted = $this->estimate;
} else {
Expand Down
Loading
Loading