GitHub Actions是GitHub的功能,它允许您根据GitHub主机为您提供的安全VM中的某些触发器运行各种操作。它有很多用途,但主要是用于构建,测试和部署应用程序的CI/CD工具。
我喜欢它。我们将其用于所有项目。它是免费的(好吧,您每月免费获得2,000分钟的VM运行时间),它的运行效果很好,并且已经整合到GitHub中。
我们还在我们的网站上讨论了how to cache npm effectively on GitHub Actions,请务必检查一下,因为它包含了一些额外的提示。
我们如何使用github动作
有很多用于GitHub动作的应用程序,但我将介绍我们每天在这里使用的应用程序。
我们的核心用例是CI/CD。我们有以下内容:
-
push
是对master
(或main
,或您的中央分支机构)完成的。 - github动作触发我们的工作流程。
- github旋转一个运行最新版本Ubuntu的VM。
- 它为我们的应用程序安装了一堆先决条件(在我们的情况下,accreditly.io是PHP,Imagick和Node之类的东西)。
- 它已经可以访问我们的代码,因此它设置了该项目(复制我们的
.env
文件,生成新的密钥,设置一些权限等)。 - 通过PHP软件包管理器作曲家安装我们的依赖项。
- 创建一个本地的SQLite数据库,并配置应用程序。
- 运行迁移以设置我们的数据库,然后运行播种机以使用假数据填充它。
- 运行
npm install
以安装我们的依赖项。 - 运行我们的完整测试套件。
- 假设一切都过去了,然后部署。
所有这些都在我们的.github/workflows/laravel.yml
文件中定义。
它的工作原理非常好。从第二个开始,将提交推向部署开始大约需要5分钟。启动VM,安装操作系统,设置具有大量依赖项的项目并运行测试套件还不错。
但是,我们可以做得更好。
优化npm install
到目前为止,我们的GitHub动作工作流程中最慢的部分是npm install
和npm run prod
(建立我们的资产),约为30秒左右。它的每一侧约为40秒,因此必须取决于可用的带宽或在任何给定时间VM的位置。无论哪种方式,这都是我们〜5min 30sec总构建时间的大量数量。
在我的本地机器上,安装和构建大约需要30秒钟。当然,我有一台不错的机器,但这是一个巨大的差距。这样做的主要原因是我们使用了大量的软件包,每个软件包都附有一系列依赖关系。那是一个很大的开销。
让我们缓存。
操作缓存
github保持一组名为actions的存储库。其中之一称为cache。
让我们从整个文件开始。
# Name of our workflow
name: Laravel
# When to run it
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
# Define our jobs
jobs:
laravel-tests:
runs-on: ubuntu-latest
# Setup
steps:
- uses: actions/checkout@v3
- name: Update apt
run: sudo apt-get update
- name: Install imagick
run: sudo apt-get install php-imagick
- uses: actions/setup-node@v3
with:
node-version: 16
- uses: nanasess/setup-php@master
with:
php-version: '8.1'
- name: Copy .env
run: php -r "file_exists('.env') || copy('.env.example', '.env');"
- name: Install Dependencies
run: composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --ignore-platform-req=ext-imagick
- name: Generate key
run: php artisan key:generate
- name: Directory Permissions
run: chmod -R 777 storage bootstrap/cache
- name: Create Database
run: |
mkdir -p database
touch database/database.sqlite
- name: Migrate
env:
DB_CONNECTION: sqlite
DB_DATABASE: database/database.sqlite
run: php artisan migrate
run: php artisan db:seed
好吧,看起来很多事情正在进行中,但是它只是在上面列表中的第1-8点遵循。它设置了我们的VM,安装了一些依赖关系,软件包并设置了我们的数据库。
现在我们需要处理NPM。我们接下来要做的是:
- 安装缓存动作模块。
- 在
~/.npm
中创建一个包含我们的包装的缓存。 - 检查是否有缓存命中(例如,我们已经有包装的缓存版本吗?)
- 继续编译。
- name: Cache node modules
id: cache-npm
uses: actions/cache@v3
env:
cache-name: cache-node-modules
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
name: List the state of node modules
continue-on-error: true
run: npm list
- name: Compile assets
run: |
npm install
npm run production
然后,我们继续运行测试和部署(我们使用Forge进行部署,因此这只是击中Webhook的一种情况):
- name: Execute tests (Unit and Feature tests) via PHPUnit
run: vendor/bin/phpunit
- name: Deploy to Laravel Forge
run: curl ${{ secrets.FORGE_DEPLOYMENT_WEBHOOK }}
将它们放在一起:
# Name of our workflow
name: Laravel
# When to run it
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
# Define our jobs
jobs:
laravel-tests:
runs-on: ubuntu-latest
# Setup
steps:
- uses: actions/checkout@v3
- name: Update apt
run: sudo apt-get update
- name: Install imagick
run: sudo apt-get install php-imagick
- uses: actions/setup-node@v3
with:
node-version: 16
- uses: nanasess/setup-php@master
with:
php-version: '8.1'
- name: Copy .env
run: php -r "file_exists('.env') || copy('.env.example', '.env');"
- name: Install Dependencies
run: composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --ignore-platform-req=ext-imagick
- name: Generate key
run: php artisan key:generate
- name: Directory Permissions
run: chmod -R 777 storage bootstrap/cache
- name: Create Database
run: |
mkdir -p database
touch database/database.sqlite
- name: Migrate
env:
DB_CONNECTION: sqlite
DB_DATABASE: database/database.sqlite
run: php artisan migrate
run: php artisan db:seed
- name: Cache node modules
id: cache-npm
uses: actions/cache@v3
env:
cache-name: cache-node-modules
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
name: List the state of node modules
continue-on-error: true
run: npm list
- name: Compile assets
run: |
npm install
npm run production
- name: Execute tests (Unit and Feature tests) via PHPUnit
run: vendor/bin/phpunit
- name: Deploy to Laravel Forge
run: curl ${{ secrets.FORGE_DEPLOYMENT_WEBHOOK }}
我们的新完整构建时间约为3分钟,这是简单地缓存NPM依赖性的巨大节省。
我们可以通过与作曲家一起做同样的事情来进一步改善这一点,但是作曲家依赖项已经很快安装。
我们目前正在考虑搬到害虫进行测试,这要快得多,尤其是在并行模式下运行时。