diff --git a/.github/workflows/laravel-test.yml b/.github/workflows/laravel-test.yml index 7ab73788..b4e264b0 100644 --- a/.github/workflows/laravel-test.yml +++ b/.github/workflows/laravel-test.yml @@ -26,6 +26,7 @@ jobs: strategy: fail-fast: false + max-parallel: 3 matrix: php-versions: ["8.1", "8.2", "8.3"] diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..a563655c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,35 @@ +name: Upload Release assets to GitHub + +on: + push: + tags: + - "*" + +jobs: + mariadb-assets: + name: Upload MariaDB assets + + strategy: + matrix: + mariadb-versions: ["10", "11"] + + uses: ./.github/workflows/upload-db-assets.yml + with: + db-type: mysql + db-version: ${{ matrix.mariadb-versions }} + + postgres-assets: + name: Upload PostgreSQL assets + + strategy: + matrix: + pgsql-versions: ["14", "15", "16"] + + uses: ./.github/workflows/upload-db-assets.yml + with: + db-type: pgsql + db-version: ${{ matrix.pgsql-versions }} + + bundle-assets: + name: Upload bundle assets + uses: ./.github/workflows/upload-file-assets.yml diff --git a/.github/workflows/laravel.yml b/.github/workflows/tests.yml similarity index 100% rename from .github/workflows/laravel.yml rename to .github/workflows/tests.yml diff --git a/.github/workflows/upload-db-assets.yml b/.github/workflows/upload-db-assets.yml new file mode 100644 index 00000000..73fccefa --- /dev/null +++ b/.github/workflows/upload-db-assets.yml @@ -0,0 +1,81 @@ +name: Publish Release db dump assets + +on: + workflow_call: + inputs: + db-type: + description: "Database type" + required: true + type: string + db-version: + description: "Database version" + required: true + type: string + +permissions: + contents: write + +env: + DB_CONNECTION: ${{ inputs.db-type }} + DB_PORT: ${{ inputs.db-type == 'mysql' && '3306' || inputs.db-type == 'pgsql' && '5432' }} + DB_USERNAME: radioroster + DB_PASSWORD: releasePassword + DB_DATABASE: radioroster + APP_ENV: production + APP_DEBUG: false + +jobs: + mariadb-release-dump: + name: Add ${{ inputs.db-type == 'mysql' && 'MariaDB' || inputs.db-type == 'pgsql' && 'PostgreSQL' }} ${{ inputs.db-version }} dump to release + runs-on: ubuntu-latest + + steps: + - if: ${{ inputs.db-type == 'mysql' }} + name: Setup MariaDB ${{ inputs.db-version }} + run: | + docker run -d --name mariadb -e MARIADB_RANDOM_ROOT_PASSWORD=true -e MARIADB_DATABASE=${{ env.DB_DATABASE }} -e MARIADB_USER=${{ env.DB_USERNAME }} -e MARIADB_PASSWORD=${{ env.DB_PASSWORD }} --publish 3306:3306 mariadb:${{ inputs.db-version }} + + - if: ${{ inputs.db-type == 'pgsql' }} + name: Setup PostgreSQL ${{ inputs.db-version }} + run: | + docker run -d --name postgres -e POSTGRES_DB=${{ env.DB_DATABASE }} -e POSTGRES_USER=${{ env.DB_USERNAME }} -e POSTGRES_PASSWORD=${{ env.DB_PASSWORD }} --publish 5432:5432 postgres:${{ inputs.db-version }} + + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + + - name: Setup PHP 8.1 + uses: shivammathur/setup-php@e8cd65f444039503a75cf4057d55442fc4316f78 + with: + php-version: "8.1" + extensions: pcntl, zip, intl, exif, mbstring, dom, fileinfo, ${{ inputs.db-type == 'mysql' && 'pdo_mysql' || inputs.db-type == 'pgsql' && 'pdo_pgsql' }} + + - name: Install Composer Dependencies + run: composer install -q --no-interaction --no-scripts --no-progress --prefer-dist --optimize-autoloader + + - name: Prepare Laravel Application + run: | + php -r "file_exists('.env') || copy('.env.example', '.env');" + php artisan key:generate + + - name: Clear config + run: php artisan config:clear + + - name: Run Migrations + run: php artisan migrate --force + + - if: ${{ inputs.db-type == 'mysql' }} + name: Dump MariaDB ${{ inputs.db-type == 'mysql' && inputs.db-version }} database + run: | + mkdir -p database/dumps + docker exec mariadb mysqldump --user $DB_USERNAME --password=$DB_PASSWORD $DB_DATABASE | gzip > database/dumps/radioroster_${{ github.ref_name }}-mariadb${{ inputs.db-version }}.sql.gz + + - if: ${{ inputs.db-type == 'pgsql' }} + name: Dump PostgreSQL ${{ inputs.db-type == 'pgsql' && inputs.db-version }} database + run: | + mkdir -p database/dumps + docker exec postgres sh -c 'export PGPASSWORD=${{ env.DB_PASSWORD }} && pg_dump -Fc -Z 6 -U${{ env.DB_USERNAME }} $DB_DATABASE' > database/dumps/radioroster_${{ github.ref_name }}-postgres${{ inputs.db-version }}.sql.gz + + - name: Upload database dump + uses: softprops/action-gh-release@v0.1.15 + with: + files: database/dumps/radioroster_${{ github.ref_name }}${{ inputs.db-type == 'mysql' && '-mariadb' || inputs.db-type == 'pgsql' && '-postgres' }}${{ inputs.db-version }}.sql.gz diff --git a/.github/workflows/upload-file-assets.yml b/.github/workflows/upload-file-assets.yml new file mode 100644 index 00000000..00467896 --- /dev/null +++ b/.github/workflows/upload-file-assets.yml @@ -0,0 +1,41 @@ +name: Upload bundle file as assets + +on: + workflow_call: + +permissions: + contents: write + +env: + APP_ENV: production + APP_DEBUG: false + +jobs: + build-assets: + name: Build assets with PHP ${{ matrix.php-versions }} + runs-on: ubuntu-latest + + strategy: + matrix: + php-versions: ["8.1", "8.2", "8.3"] + + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + + - name: Setup PHP ${{ matrix.php-versions }} + uses: shivammathur/setup-php@e8cd65f444039503a75cf4057d55442fc4316f78 + with: + php-version: ${{ matrix.php-versions }} + extensions: pcntl, zip, intl, exif, mbstring, dom, fileinfo + + - name: Install Composer Dependencies + run: composer install -q --no-interaction --no-scripts --no-progress --prefer-dist --optimize-autoloader + + - name: Compress into Zip file + run: zip -r -q -9 -X radioroster_${{ github.ref_name }}-php${{ matrix.php-versions }}.zip . + + - name: Upload zip file as asset + uses: softprops/action-gh-release@v0.1.15 + with: + files: radioroster_${{ github.ref_name }}-php${{ matrix.php-versions }}.zip diff --git a/app/Http/Middleware/JsonOnlyMiddleware.php b/app/Http/Middleware/JsonOnlyMiddleware.php index 1188a226..2535c71b 100644 --- a/app/Http/Middleware/JsonOnlyMiddleware.php +++ b/app/Http/Middleware/JsonOnlyMiddleware.php @@ -15,7 +15,7 @@ class JsonOnlyMiddleware */ public function handle(Request $request, Closure $next): Response { - if (!empty($request->all()) && !$request->isJson()) { + if (!empty($request->getContent()) && !$request->isJson()) { return response()->json([ 'message' => 'Only JSON requests are accepted' ], Response::HTTP_BAD_REQUEST); diff --git a/tests/Feature/Http/Middleware/JsonOnlyMiddlewareTest.php b/tests/Feature/Http/Middleware/JsonOnlyMiddlewareTest.php index 1aee383b..f29dfa1a 100644 --- a/tests/Feature/Http/Middleware/JsonOnlyMiddlewareTest.php +++ b/tests/Feature/Http/Middleware/JsonOnlyMiddlewareTest.php @@ -18,13 +18,19 @@ public function test_non_json_requests_are_rejected(): void 'password' => bcrypt('ValidPassword'), ]); - $response = $this->post('/api/v1/login', [ - 'body' => '<?xml version="1.0" encoding="UTF-8"?> + $response = $this->call( + 'POST', + '/api/v1/login', + server: $this->transformHeadersToServerVars([ + 'Accept' => 'text/xml, application/xml, text/plain', + 'Content-Type' => 'text/xml, application/xml, text/plain', + ]), + content: '<?xml version="1.0" encoding="UTF-8"?> <root> <email>valid@example.com</email> <password>ValidPassword</password> </root>' - ], ['Content-Type' => 'text/xml']); + ); $response->assertStatus(400) ->assertJson([