З Новим Роком! 🎉 Вступаючи в новий рік, наповнений можливостями та викликами, саме час вдосконалити наші процеси та впроваджувати автоматизацію в робочі процеси. Сьогодні я хочу поділитися тим, як я вирішував деякі проблеми у своєму робочому процесі GitHub Actions CI/CD під час деплою .NET Web API на віддалений сервер (в моєму випадку, Droplet на Digitalocean).
Цей досвід не тільки оптимізував мій робочий процес, а й став нагадуванням про важливість безпечної обробки чутливих даних — таких як SSH-дані для доступу — за допомогою GitHub Secrets, як ви побачите в прикладах цього матеріалу.
Сценарій
Мій робочий процес GitHub Actions складався з двох основних задач:
- Задача на побудову: для публікації артефактів .NET Web API.
- Задача на деплой: для перенесення артефактів на віддалений сервер і перезапуску сервісу застосунку.
Проблема
Я зіткнувся з двома основними проблемами:
- Крок завантаження артефактів у задачі побудови вказував на неправильну директорію публікації.
- Крок деплою не вдалося виконати через відсутність опублікованих файлів і неправильну обробку віддалених директорій.
Рішення
Ось як я вирішив ці проблеми:
1. Налаштування GitHub Secrets для чутливих даних
Перш за все, я переконався, що вся чутлива інформація, така як SSH-дані, зберігається в GitHub Secrets. Така практика допомагає захистити дані з високим рівнем чутливості, зокрема:
SSH_HOST
SSH_USER
SSH_KEY
SSH_PASSPHRASE
Ці секрети використовувались у робочому процесі безпечно, гарантуючи, що вони не потраплять в логи.
2. Правильне визначення директорії публікації
Задача побудови використовувала наступний крок для того, щоб артефакти публікувались у правильну директорію:
- name: Publish API
id: publish_api
run: |
API_PROJECT_PATH="CompanyName.ProductName.API"
PUBLISH_DIR="$(pwd)/$API_PROJECT_PATH/publish" # Явно задаємо шлях публікації
dotnet publish $API_PROJECT_PATH/CompanyName.ProductName.API.csproj -c Release --no-build --no-restore --property:PublishDir=$PUBLISH_DIR
echo "publish_path=$PUBLISH_DIR" >> $GITHUB_ENV
3. Перенесення файлів на віддалений сервер
Задача деплою використовує appleboy/scp-action
для безпечного перенесення артефактів на віддалений сервер:
- name: Transfer Files to Remote Server
uses: appleboy/[email protected]
with:
source: ./publish/*
target: /my/full/application/path/
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
passphrase: ${{ secrets.SSH_PASSPHRASE }}
overwrite: true
Це гарантувало, що:
- Цільова директорія створюється, якщо вона не існує.
- Файли передаються безпечно.
- Існуючі файли в цільовій директорії перезаписуються за потреби.
4. Перезапуск застосунку
Останнім кроком було перезапуск сервісу застосунку, налаштованого як Linux Daemon (systemd).
The step uses appleboy/ssh-action
to remotely access the server and run commands to restart the service:
- name: Restart Web API Service
uses: appleboy/[email protected]
with:
host: ${{ secrets.SSH_HOST }}
key: ${{ secrets.SSH_KEY }}
username: ${{ secrets.SSH_USER }}
passphrase: ${{ secrets.SSH_PASSPHRASE }}
script: |
sudo chown -R www-data:www-data /my/full/application/path/
sudo systemctl restart apiservice
Повний скрипт робочого процесу
Оскільки я зосередився лише на тих ділянках, де мав проблеми з робочим процесом, я вирішив поділитися повним скриптом файлу робочого процесу GitHub Actions після внесення необхідних виправлень:
name: Build & Deploy
on:
push:
branches: [main]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.x'
- name: Restore Dependencies
run: dotnet restore CompanyName.ProductName.sln
- name: Build Solution
run: dotnet build CompanyName.ProductName.sln -c Release --verbosity minimal --no-restore
- name: Publish API
id: publish_api
run: |
API_PROJECT_PATH="CompanyName.ProductName.API"
PUBLISH_DIR="$(pwd)/$API_PROJECT_PATH/publish" # Явно задаємо шлях публікації
dotnet publish $API_PROJECT_PATH/CompanyName.ProductName.API.csproj -c Release --no-build --no-restore --property:PublishDir=$PUBLISH_DIR
echo "publish_path=$PUBLISH_DIR" >> $GITHUB_ENV
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: published-app
path: ./publish/
deploy:
name: Deploy Web API
needs: build
runs-on: ubuntu-latest
steps:
- name: Download Artifact
uses: actions/download-artifact@v3
with:
name: published-app
path: ./publish
- name: Transfer Files to Remote Server
uses: appleboy/[email protected]
with:
source: ./publish/*
target: /my/full/application/path/
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
passphrase: ${{ secrets.SSH_PASSPHRASE }}
overwrite: true
- name: Restart Web API Service
uses: appleboy/[email protected]
with:
host: ${{ secrets.SSH_HOST }}
key: ${{ secrets.SSH_KEY }}
username: ${{ secrets.SSH_USER }}
passphrase: ${{ secrets.SSH_PASSPHRASE }}
script: |
sudo chown -R www-data:www-data /my/full/application/path/
sudo systemctl restart apiservice
Ключові висновки
- Захищайте ваші секрети: Завжди використовуйте GitHub Secrets для керування чутливими даними в робочих процесах.
- Явно визначайте шляхи: Уникайте непорозумінь, явно визначаючи шляхи до файлів для кожного кроку.
- Обробляйте віддалені директорії: Переконайтесь, що цільові директорії для деплою створюються або очищаються за необхідності.
З цими виправленнями робочий процес тепер працює без проблем, дозволяючи автоматизувати деплой .NET Web API через GitHub Actions.
Перетинаючи межі нового року, давайте продовжувати ділитися знаннями і покращувати наші робочі процеси. Якщо ви зіткнулися з подібними проблемами або маєте питання, не соромтеся ділитися ними в коментарях. Давайте розвиватися разом у 2025 році!
Перекладено з: Resolving CI/CD Workflow Issues with GitHub Actions for API Deployment to a VPS