Skip to main content

Cloudsoft Zone Build, deploy and scale with practical guides to PHP, Node.js, React, DevOps and AI automation. Explore the guides

Cloudsoft Zone
DevOpsDevelopmentLaravelPHPTutorial

Laravel CI/CD with GitHub Actions: verification, release artifacts and guarded deployment

Build Laravel CI/CD with GitHub Actions using locked dependencies, isolated verification, immutable release artifacts and a protected deployment job with explicit recovery gates.

Nilesh Kushvaha

5 min read

Laravel artwork with a GitHub Actions release pipeline covering verification, artifact identity and guarded deployment.
Image: Cloudsoft Zone layout; Laravel / Public domain
In this article

A Laravel pull request passes its tests, but production fails because the release uses different PHP extensions or rebuilds a different frontend dependency tree. A pipeline should establish what was checked, what was built and exactly what was deployed.

Laravel CI/CD with GitHub Actions starts with a credential-free verification job, then adds real infrastructure checks. A Laravel GitHub Actions workflow should build one identified release artifact, and a Laravel CI pipeline must protect deployment authority before anything reaches production.

Laravel CI/CD with GitHub Actions needs three separate boundaries: verification without production authority, an identified release artifact and guarded promotion. This guide provides a starter CI workflow and the additional contracts required before connecting it to a VPS.

Use the Laravel production deployment checklist alongside the pipeline. A green workflow is meaningful only when its checks match the application's real release risks.

Pull request verification is separated from trusted artifact creation and a protected deployment job.
Passing CI does not grant a pull request authority to publish or deploy.

Step 1: Match PHP and dependency inputs

Select a supported PHP version and the extensions required by the application and Laravel. Review composer.json and composer.lock; do not rely on whatever happens to be installed on a hosted runner.

Install from the lockfile rather than updating dependencies during deployment. If the application builds frontend assets, use its committed package-manager lockfile and the same supported Node version across CI and the release build.

Record these versions in the pipeline configuration. A cache is an optimization, not an alternative source of truth for missing or inconsistent lockfiles.

Step 2: Begin with a credential-free verification job

The following starter assumes a conventional Laravel application with .env.example, a Composer lockfile and tests that can use SQLite. PHP 8.4 is an explicit example choice to confirm against your application. The action tags make the example readable; replace them with reviewed full commit SHAs before production adoption.

YAML
name: Laravel verification
on:
  pull_request:
  push:
    branches: [main]
permissions:
  contents: read
jobs:
  verify:
    runs-on: ubuntu-24.04
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v6
        with:
          persist-credentials: false
      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.4'
          extensions: mbstring, pdo_sqlite, dom, fileinfo
          coverage: none
      - run: composer install --no-interaction --prefer-dist --no-progress
      - run: cp .env.example .env
      - run: php artisan key:generate
      - run: php artisan test
        env:
          APP_ENV: testing
          DB_CONNECTION: sqlite
          DB_DATABASE: ':memory:'
          CACHE_STORE: array
          SESSION_DRIVER: array
          QUEUE_CONNECTION: sync

This is fast application verification, not a complete production deployment workflow. Check phpunit.xml and application configuration for overrides. Add every application-required extension and build step rather than weakening checks to fit the sample.

Step 3: Add real infrastructure checks

SQLite can differ from MySQL in SQL behavior, types, locking and migration semantics. Use disposable MySQL matching production for relevant integration cases. Add Redis-backed checks when cache locks, sessions or queues depend on it.

Use synthetic credentials and data only. Never point a CI verification job at a retained production database. Keep its schema setup scoped to the disposable environment.

Verification layer Important evidence
Fast application checks Validation and application rules behave correctly
Database integration Migrations and queries work on the intended engine
Queue integration Dispatch, retries and worker behavior match the backend
Frontend build Required assets are generated from locked dependencies
Production rehearsal Built artifact starts under production configuration

Document the expected failure behavior too: a missing required setting should fail clearly, not silently select a different service.

Tie an exact source commit to a built release and promote that same artifact.
Do not rebuild a different dependency graph on the production host.

Step 4: Build one identified release artifact

Build from the reviewed source commit. Include the needed Composer production dependencies, compiled frontend assets and release metadata. Exclude real environment files, debug exports and uploaded customer files.

An archive checksum or container digest should identify the promoted release. Store the source commit and build inputs alongside it so an operator can trace a deployment back to the inspected code.

Do not reuse a mutable latest label as the only identity. Also do not assume that passing tests with development dependencies establishes that a production artifact excluding them can boot. Rehearse that actual artifact separately.

Step 5: Protect deployment authority

Use a dedicated production environment with the supported protection rules, approved branches and scoped secrets. Availability of particular protections depends on repository visibility and plan; verify the controls your repository actually supports.

Keep privileged deployment separate from untrusted pull request code. Avoid checking out a fork's code in a privileged pull_request_target job. Pin third-party actions and review workflow changes as executable release code.

Serialize production operations through the release owner. Do not cancel an active migration merely because a newer commit arrived. A concurrency policy must reflect the safe interruption points of the deployment procedure.

Step 6: Use the existing deployment adapter

The protected job should invoke a reviewed deployment script or API with the exact artifact identity. That owner handles permissions, shared storage, schema compatibility, worker reloads and acceptance checks.

Avoid an inline SSH script that mixes cloning, dependency updates, migrations and process restarts without error boundaries. Verify the host identity and restrict the deployment account to the actual application scope.

Our single-VPS deployment guide covers the runtime boundary. Adapt the pipeline to that process rather than creating a second deployment implementation.

Verify compatibility and user acceptance while retaining a defined recovery path.
Database changes can outlive a code rollback.

Step 7: Define acceptance and recovery gates

Failure Required pipeline response
Verification fails No deployable release is promoted
Artifact identity differs Promotion stops
Migration fails No blind code switch or destructive rollback
Public acceptance fails Preserve evidence and follow compatible recovery
Deployment caller disconnects Resolve actual operation state before retry

Retain the previous compatible artifact and document when a code rollback is insufficient. Database changes and external side effects may require forward repair.

Rehearse the pipeline in an isolated environment before supplying production authority. For a GitHub Actions release process tailored to your Laravel application, discuss the project with Cloudsoft Zone.

Featured image: Cloudsoft Zone technical layout with laravel artwork by Laravel (Public domain). Product mark resized proportionally for identification; no endorsement implied. Layout: CC BY-SA 4.0.

Frequently asked questions

  • Does a SQLite CI pass prove production MySQL compatibility?

    No. Keep fast checks if useful, but add isolated checks against the actual production database engine and relevant Redis or queue behavior.

  • Should pull request workflows receive production deployment secrets?

    No. Separate untrusted verification from a protected trusted deployment job.

  • Can I deploy by rebuilding dependencies on the VPS?

    That can produce a different release. Prefer promoting an identified artifact built from the reviewed commit and lockfiles.

Sources

  1. Laravel deployment requirements and runtime optimization — Laravel
  2. GitHub workflow security and action pinning — GitHub
  3. Protected deployment environments — GitHub
  4. PHP setup action inputs — shivammathur/setup-php
  5. GitHub workflow syntax and concurrency — GitHub

Comments

No comments yet. Be the first to join the conversation.

Leave a comment

Every comment is read by a moderator before it appears. Your email address is never published; it is used only to contact you about this comment.

Never published. Used only to contact you about this comment.

Loading the security check…

Comments are moderated before publication.