Najskuteczniejsze
GitHub Actions
dla programistów PHP
Lighting Talk
Aleksander Tabor
PHP Developer
aleksandertabor.com
linkedin.com/in/aleksander-tabor
github.com/aleksandertabor�alekx.tabor@gmail.com
Czym są GitHub Actions i do czego się przydają?
Niski próg wejścia
Eventy, po których wiesz, że coś się dzieje…
Link: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows
Szereg akcji przy Pull Requescie
Workflow GitHub Action - plik .yml w .github/workflows
Źródło: https://www.youtube.com/watch?v=Tz7FsunBbfQ
Testy PHPUnit
name: deployment # workflow => .github/workflows/deployment.yml
on:
workflow_dispatch: # event
push: # event
paths:
- "**"
jobs:
tests: # job
runs-on: ubuntu-latest # operation system
services:
mysql:
image: bitnami/mysql:8.0
env:
MYSQL_ROOT_PASSWORD: password
MYSQL_USER: sail
MYSQL_DATABASE: testing
MYSQL_PASSWORD: password
MYSQL_AUTHENTICATION_PLUGIN: mysql_native_password
ports:
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=10
steps: # steps
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
tools: composer:v2
Testy PHPUnit #2
- name: Mysql privileges
run: mysql --host 127.0.0.1 --port 3306 --user="root" --password="password" --execute="GRANT ALL PRIVILEGES ON *.* TO sail@'%';"
- name: Get composer cache directory
id: composer-cache
working-directory: ./
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache dependencies
uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install composer dependencies
working-directory: ./
run: composer install
- name: Setup env for testing
working-directory: ./
run: |
sed -ri "s/^DB_HOST=mysql/DB_HOST=127.0.0.1/" .env.testing
sed -ri "s/^DB_PORT=3306/DB_PORT=${{ job.services.mysql.ports[3306] }}/" .env.testing
Testy PHPUnit #3
- name: PhpUnit
working-directory: ./
run: php artisan test --parallel
Testy PHPUnit #4
Testy PHPUnit #5
Deployment
deploy-staging:
runs-on: ubuntu-latest
needs: tests-job
if: github.ref == 'refs/heads/master'
steps:
- uses: actions/checkout@v4
- name: Install SSH key
uses: shimataro/ssh-key-action@v2
with:
key: ${{ secrets.SSH_KEY_STAGING }}
known_hosts: ${{ secrets.KNOWN_HOSTS_STAGING }}
- name: Deploy
working-directory: ./deployer
run: php deployer.phar -f web.php deploy staging
Testy Laravel Dusk z Artifacts
- name: Upgrade Chrome Driver
run: php artisan dusk:chrome-driver `/opt/google/chrome/chrome --version | cut -d " " -f3 | cut -d "." -f1`
- name: Start Chrome Driver
run: ./vendor/laravel/dusk/bin/chromedriver-linux
- name: Run Dusk
run: |
php artisan serve --no-reload & php artisan dusk
env:
APP_URL: "http://127.0.0.1:8000"
APP_ENV: "testing"
- name: Upload dusk screenshots
uses: actions/upload-artifact@v4
if: ${{ failure() }}
with:
name: dusk-screenshots
path: tests/Browser/screenshots
Testy Laravel Dusk z Artifacts #2
Testy Laravel Dusk z Artifacts #3
Static Analysis z Annotations
- name: PhpStan
working-directory: ./
run: php vendor/bin/phpstan analyse --memory-limit=2G --error-format=github
Comment Pull Request Action
- name: Comment PR
uses: thollander/actions-comment-pull-request@v2
with:
message: |
# New comment 🔗
New comment body
Git Auto Commit Action
- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: ♻️ Refactor code
Git Auto Commit Action #2 - Rector
rector-job:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
tools: composer:v2
- run: git pull
- run: composer install --no-interaction --no-progress --no-suggest
- run: vendor/bin/rector process --ansi
- name: Check for Rector modified files
id: rector-git-check
run: echo ::set-output name=modified::$(if git diff --exit-code --no-patch; then echo "false"; else echo "true"; fi)
- name: Commit changes
if: steps.rector-git-check.outputs.modified == 'true'
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: ♻️ Refactor code
Git Auto Commit Action #3 - PHP CS Fixer
php-cs-fixer-job:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
tools: composer:v2
- name: Install composer dependencies
working-directory: ./
run: composer install --no-interaction --no-progress --no-suggest
- name: PhpCs
working-directory: ./
run: php vendor/bin/php-cs-fixer fix --config=.php_cs.dist.php --allow-risky=yes
- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: 🎨 Fix styling
Notyfikacje Slack
- name: Slack Notification
uses: rtCamp/action-slack-notify@v2
if: ${{ failure() }}
env:
SLACK_USERNAME: Tests Bot
SLACK_ICON_EMOJI: ':fire:'
SLACK_COLOR: ${{ job.status }}
SLACK_MESSAGE: Laravel Dusk Tests Failed
SLACK_FOOTER: by Aleksander Tabor
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
Notyfikacje Slack #2
Zmiany w paczkach Composer
name: Composer Diff
on:
pull_request:
paths:
- 'composer.lock'
permissions:
contents: read
pull-requests: write
jobs:
composer-diff:
name: Composer Diff
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate composer diff
id: composer_diff
uses: IonBazan/composer-diff-action@v1
Zmiany w paczkach Composer #2
- uses: marocchino/sticky-pull-request-comment@v2
if: ${{ steps.composer_diff.outputs.composer_diff_exit_code != 0 }}
with:
header: composer-diff
message: |
<details>
<summary>Composer package changes</summary>
${{ steps.composer_diff.outputs.composer_diff }}
</details>
Zmiany w paczkach Composer #3
GitHub Actions Schedule - wtedy kiedy śpimy…
name: Scheduler
on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
jobs:
schedule-job:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Fetch all branches
run: git fetch --all
- name: Get commits from last day
id: get-commits
run: |
git log --since="1 day ago" --format="%H %ad %s" --date=format:'%Y-%m-%d %H:%M:%S' --all > commits.txt
GitHub Actions Schedule - wtedy kiedy śpimy… #2
- name: Post commits as comment
id: get-parsed-commits
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const path = './commits.txt';
if (fs.existsSync(path)) {
const content = fs.readFileSync(path, 'utf8');
const lines = content.split('\n');
const commits = lines.map(line => {
const [commitHash, ...message] = line.split(' ');
return `- [\`${commitHash}\`](https://github.com/${{ github.repository }}/commit/${commitHash}) - ${message.join(' ')}`;
}).join('\n');
const issue_number = 327;
const commentBody = `### Last Day Commits:\n${commits}`;
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue_number,
body: commentBody
});
} else {
throw new Error(`File ${path} does not exist`);
}
GitHub Actions Schedule - wtedy kiedy śpimy… #3
Labeler Action
name: Label Pull Requests
on: [pull_request]
permissions:
contents: read
pull-requests: write
jobs:
labeler:
name: Label Pull Requests Job
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: actions/labeler@v5
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
sync-labels: true
configuration-path: .github/labeler.yml
dot: true
Labeler Action #2
routes:
- changed-files:
- any-glob-to-any-file: 'routes/web.php'
migrations:
- changed-files:
- any-glob-to-any-file:
- database/migrations/*
Labeler Action #3
Dalsza zabawa - routing aplikacji jako komentarz PR
name: Show routes
on: [pull_request]
permissions:
contents: read
pull-requests: write
jobs:
show-routes-job:
name: Show routes job
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
tools: composer:v2
- name: Install composer dependencies
working-directory: ./
run: composer install --no-interaction --no-progress --no-suggest
Dalsza zabawa - routing aplikacji jako komentarz PR #2
- name: Vendor Route List
id: vendor-route-list
working-directory: ./
run: |
echo "::set-output name=results::$(php artisan route:list --only-vendor --json)"
- uses: buildingcash/json-to-markdown-table-action@v1
id: table
with:
json: ${{ steps.vendor-route-list.outputs.results }}
- name: Comment PR
uses: thollander/actions-comment-pull-request@v2
with:
message: |
# Routes list 🔗
All routes in your application.
${{ steps.table.outputs.table }}
Dalsza zabawa - routing aplikacji jako komentarz PR #3
Dependabot
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
labels:
- "dependencies"
- package-ecosystem: "composer"
directory: "/"
schedule:
interval: "weekly"
labels:
- "php"
- "dependencies"
Dependabot
Actionlint
Link: https://github.com/rhysd/actionlint
Wsparcie IDE
Link: https://plugins.jetbrains.com/plugin/21396-github-workflow
Jira
Co dalej?
Link: https://github.com/marketplace?type=actions&query=php
GitHub Actions Certificate
Link: https://examregistration.github.com/certification/ACTIONS
Co jeszcze możemy zrobić z GitHub Actions?
Źródła, wiedza
Link: https://github.com/aleksandertabor/PHPers-Summit-2024-Najskuteczniejsze-GitHub-Actions-dla-programistow-PHP
Dziękuję
Q&A