Automating Deployment for Laravel Using Deployer and GitHub Actions

Overview

In this note, we outline how to automate the deployment process for a Laravel project using Deployer and GitHub Actions. The setup covers deploying to both staging and production environments, with different workflows for each environment. We also integrate necessary post-deployment tasks such as running migrations and restarting queues using Supervisor.

Prerequisites

Before setting up this automation, ensure the following:

  • Deployer is installed in your Laravel project (composer require deployer/deployer --dev).
  • The deploy.php configuration file is created in the root of your project.
  • SSH keys are set up correctly between GitHub Actions and your server for secure deployment.

Deployment Setup

Step 1: Creating the deploy.php File

The deploy.php file is essential for configuring Deployer. It defines the repository, shared directories, writable directories, and host settings for both staging and production environments. Below is an example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php
namespace Deployer;

require 'recipe/laravel.php';

// Project repository
set('repository', '[email protected]:your-username/your-repo.git');

// Shared files/dirs between deploys
add('shared_files', ['.env']);
add('shared_dirs', ['node_modules', 'vendor']);

// Writable dirs by web server
add('writable_dirs', []);

// Hosts
host('staging')
->set('hostname','IP')
->set('remote_user', 'deployer')
->set('branch', 'staging')
->set('deploy_path', '/var/www/staging');

host('production')
->set('hostname','IP')
->set('remote_user', 'deployer')
->set('branch', 'main')
->set('deploy_path', '/var/www/production');

// Tasks
desc('Restart PHP-FPM service');
task('php-fpm:restart', function () {
run('sudo systemctl restart php7.4-fpm');
});

desc('Restart supervisor service');
task('supervisor:restart', function () {
run('sudo supervisorctl reread');
run('sudo supervisorctl update');
run('sudo supervisorctl restart all');
});

// Hooks
after('deploy:symlink', 'php-fpm:restart');
after('deploy:symlink', 'artisan:migrate');
after('deploy:symlink', 'supervisor:restart');

Step 2: GitHub Actions Workflow

Staging Workflow (staging-deploy.yml)

The following is an example of a GitHub Actions workflow file for deploying to the staging environment.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
name: Deploy to Staging

on:
push:
branches:
- staging

jobs:
deploy:
name: Deploy to Staging
runs-on: ubuntu-latest

steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'

- name: Install Composer Dependencies
run: composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader

- name: Deploy to Staging
uses: deployphp/action@v1
with:
private-key: ${{ secrets.SSH_KEY }}
dep: deploy staging

Production Workflow (production-deploy.yml)

The production workflow is similar but triggers on pushes to the main branch.

Step 3: Testing and Troubleshooting

Common Errors

  1. No host selected: This error occurs when Deployer cannot find the host based on the command selector. Make sure you pass the correct host (either staging or production) when deploying.

    1
    ./vendor/bin/dep deploy staging
  2. Call to undefined method: This error may appear if you’re using the wrong Deployer version or method. In our case, ensure you’re following the Deployer 7.x documentation.

Step 4: Post-Deployment Tasks

  1. Running Migrations: We use the artisan:migrate command to ensure that migrations are run automatically after deployment.

  2. Restarting Queues: If changes to the queue system are deployed, it’s essential to restart the queue workers. We achieve this by running artisan:queue:restart after deployment.

  3. Restarting Supervisor: If you’re managing workers using Supervisor, the deployment process includes commands to restart Supervisor with supervisorctl.


Summary

By combining Deployer and GitHub Actions, we’ve automated the deployment process for a Laravel project across both staging and production environments. This approach ensures the project is deployed and migrations are run automatically, and queue workers are restarted when necessary. The process is both scalable and adaptable for future projects.

Sources

  1. Deployer Documentation: Hosts in Deployer 7.x
    https://deployer.org/docs/7.x/hosts

  2. Deployer GitHub Action
    https://github.com/deployphp/action

  3. Deployer Official Documentation: Version 7.x
    https://deployer.org/docs/7.x/

  4. GitHub Actions Documentation: Workflow Syntax
    https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions

Masterclass Notes on Radio Advertising

Introduction

Companies buy reach instead of a number of spots. This reach represents the number of listeners at a given moment, such as during rush hour. The number of spots does not matter if the reach is low. You have gross reach, average contact frequency (GCF), and Net reach. Net reach refers to the number of unique listeners, while gross reach does not distinguish between them. The GCF measures how often a listener hears a spot.

Example Calculation

$Gross = 2.583.958$
$GCF = 4$
$Net = \frac{Gross}{GCF} = 645.989,50 \approx 645.990 \text{ Unique listeners}$


Understanding GRP (Gross Rating Point)

Radio stations use Gross Rating Point (GRP), which works with target groups and percentages. A GRP of 5 means that 5% of the target group was reached. This can be filtered by age, gender, country, etc., with age being the most common filter. GRP adds up, so Net listeners do not matter. For example, $2 \times 5%$ GRP simply becomes 10% GRP.

Important Considerations

  • Average Contact Frequency: Always pay attention to the GCF.
  • Target Groups: Some age groups are more difficult to reach.
  • Campaign Duration: Longer campaigns may be necessary for less popular stations.

Data Sources: National Listening Survey (NLO)

The National Listening Survey (NLO) provides data on the number of listeners to major radio stations. NLO participants maintain a diary every fifteen minutes over two months, noting which station they listen to.

Key Statistics

  • 15.000.000 listeners monthly to large radio stations.
  • Market share is recorded as a percentage of listeners aged ten years or older.

Choosing the Right Station

To advertise effectively, assess the most cost-efficient way to reach your target group. Many advertisers mistakenly choose stations based on assumptions rather than data.


Campaign Pricing Factors

Basic Annual Price (BJP)

The BJP represents how much you will pay per year for a basic number of spots. Discounts may apply for bulk spot purchases.

Spot Length

Radio stations base prices on a standard spot length of 20 seconds. Prices adjust in increments of 5 seconds for shorter or longer spots.

Monthly Rate Example

$BJP = 200 \text{ euros}$
$\text{Spot length} = 35 \text{ seconds}$
$Index = 175 \text{ euros}$
$\text{Monthly rate} = 175 \times 200 = 35.000 \text{ euros per month}$


Advertiser Packages

Advertiser packages offer different conditions such as priority in scarcity situations, and how quickly reach can be used (distribution).

Example: GRP Target

Suppose you want a GRP of 3.5 million people in a month on NPO Radio 2. With distribution, you can limit the campaign to stop once that GRP is reached, avoiding unnecessary extra costs.


Time Slots and Indexing

Time slots indicate when something is broadcast during the day (e.g., 6-24, 9-14). Some companies calculate these as a separate index.

Target groups also determine the price. Factors such as demand, supply, and size influence the cost.

Market Index

Radio stations use a market index to balance supply and demand. Prices may fluctuate based on demand and availability.

Monthly Index

The monthly index tracks how much spot time costs each month. For example, advertising costs may rise during holiday months due to increased demand.


Additional Options

Some packages include additional options, or they may be billed separately:

  • Preferred Positions: Your preference for spot position (e.g., last, first).
  • Roadblocks: A group of channels plays a spot simultaneously.

GRP Price Calculation

The GRP price is calculated by multiplying the following factors:

$\text{GRP price} = \text{BJP} \times \text{spot length index} \times \text{package index} \times \text{time slot index} \times \text{target group index} \times \text{market index} \times \text{month index}$


Conclusion

All radio stations use fixed costs per spot rather than GRPs, derived from second rates. For companies that prefer not to delve deeply into GRP mechanics, second rates may be the best choice for maximizing reach.