fix(ci-cd): add github workflows

This commit is contained in:
2025-12-11 11:23:55 +03:00
parent e3e9d14ea9
commit 3afa1fbb7b
4 changed files with 197 additions and 48 deletions

137
.github/workflows/main.yaml vendored Normal file
View File

@@ -0,0 +1,137 @@
name: Build and deploy
on:
push:
branches:
- 'main'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Notify Telegram start building
uses: appleboy/telegram-action@master
with:
to: ${{ secrets.TELEGRAM_CHAT_ID }}
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
message: |
🚀 Запуск сборки!
Сервер: ${{ secrets.SERVER_NAME }}
Репозиторий: ${{ github.repository }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: smallbuster/ocenka-web:latest
build-args: |
NEXT_PUBLIC_MAIL_USER=${{ secrets.NEXT_PUBLIC_MAIL_USER }}
NEXT_PUBLIC_MAIL_PASS=${{ secrets.NEXT_PUBLIC_MAIL_PASS }}
NEXT_PUBLIC_MAIL_FROM=${{ secrets.NEXT_PUBLIC_MAIL_FROM }}
NEXT_PUBLIC_MAIL_TO=${{ secrets.NEXT_PUBLIC_MAIL_TO }}
NEXT_PUBLIC_MAIL_SECURE_KEY=${{ secrets.NEXT_PUBLIC_MAIL_SECURE_KEY }}
- name: Notify Telegram about success
if: success()
uses: appleboy/telegram-action@master
with:
to: ${{ secrets.TELEGRAM_CHAT_ID }}
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
message: |
✅ Сборка успешно завершена!
Сервер: ${{ secrets.SERVER_NAME }}
Репозиторий: ${{ github.repository }}
Ветка: ${{ github.ref_name }}
Коммит: ${{ github.sha }}
- name: Notify Telegram about failure
if: failure()
uses: appleboy/telegram-action@master
with:
to: ${{ secrets.TELEGRAM_CHAT_ID }}
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
message: |
❌ Сборка проекта неудачна!
Сервер: ${{ secrets.SERVER_NAME }}
Репозиторий: ${{ github.repository }}
Ветка: ${{ github.ref_name }}
Коммит: ${{ github.sha }}
Подробности: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
deploy:
runs-on: self-hosted
needs: build
steps:
- name: Notify Telegram start deploy
uses: appleboy/telegram-action@master
with:
to: ${{ secrets.TELEGRAM_CHAT_ID }}
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
message: |
🐳 Запуск деплоя!
Сервер: ${{ secrets.SERVER_NAME }}
Репозиторий: ${{ github.repository }}
- name: Checkout repository
uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Compose
run: |
docker compose version
- name: Stop and remove existing containers
run: |
docker compose -f docker-compose.yaml down || true
- name: Pull Docker images
run: |
docker compose -f docker-compose.yaml pull
- name: Start containers
run: |
docker compose -f docker-compose.yaml up -d
- name: Notify Telegram about success
if: success()
uses: appleboy/telegram-action@master
with:
to: ${{ secrets.TELEGRAM_CHAT_ID }}
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
message: |
✅ Деплой успешно завершен!
Сервер: ${{ secrets.SERVER_NAME }}
Репозиторий: ${{ github.repository }}
Ветка: ${{ github.ref_name }}
Коммит: ${{ github.sha }}
- name: Notify Telegram about failure
if: failure()
uses: appleboy/telegram-action@master
with:
to: ${{ secrets.TELEGRAM_CHAT_ID }}
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
message: |
❌ Деплой не удался!
Сервер: ${{ secrets.SERVER_NAME }}
Репозиторий: ${{ github.repository }}
Ветка: ${{ github.ref_name }}
Коммит: ${{ github.sha }}
Подробности: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}

6
.idea/compiler.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="TypeScriptCompiler">
<option name="useServicePoweredTypesWasEnabledByExperiment" value="true" />
</component>
</project>

82
.idea/workspace.xml generated
View File

@@ -5,26 +5,10 @@
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="2a96f817-9dc2-4f3c-893a-c4974c750774" name="Changes" comment=""> <list default="true" id="2a96f817-9dc2-4f3c-893a-c4974c750774" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/.github/workflows/main.yaml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/compiler.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/api/og-image/lib/render.ts" beforeDir="false" /> <change beforePath="$PROJECT_DIR$/Dockerfile" beforeDir="false" afterPath="$PROJECT_DIR$/Dockerfile" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/api/og-image/lib/template.tsx" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/api/og-image/lib/types.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/api/og-image/route.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/api/og/route.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/api/og/route.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/contacts/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/contacts/page.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/cookies/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/cookies/page.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/experts/borodin-vitalij-petrovich/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/experts/borodin-vitalij-petrovich/page.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/experts/gjulmamedov-javar-firmamed-ogly/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/experts/gjulmamedov-javar-firmamed-ogly/page.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/experts/jancen-jana-nikolaevna/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/experts/jancen-jana-nikolaevna/page.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/experts/kaminskij-dmitrij-olegovich/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/experts/kaminskij-dmitrij-olegovich/page.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/experts/kolodij-aleksandr-sergeevich/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/experts/kolodij-aleksandr-sergeevich/page.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/experts/mikova-inna-georgievna/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/experts/mikova-inna-georgievna/page.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/experts/mitjaev-aleksej-aleksandrovich/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/experts/mitjaev-aleksej-aleksandrovich/page.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/experts/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/experts/page.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/experts/polinov-andrej-vladimirovich/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/experts/polinov-andrej-vladimirovich/page.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/experts/volkova-goncharova-tatjana-anatolevna/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/experts/volkova-goncharova-tatjana-anatolevna/page.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/privacy-policy/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/privacy-policy/page.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/user-agreement/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/user-agreement/page.tsx" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -32,7 +16,7 @@
<option name="LAST_RESOLUTION" value="IGNORE" /> <option name="LAST_RESOLUTION" value="IGNORE" />
</component> </component>
<component name="DarkyenusTimeTracker"> <component name="DarkyenusTimeTracker">
<option name="totalTimeSeconds" value="223885" /> <option name="totalTimeSeconds" value="225852" />
<option name="gitIntegration" value="true" /> <option name="gitIntegration" value="true" />
<option name="naggedAbout" value="1" /> <option name="naggedAbout" value="1" />
</component> </component>
@@ -60,32 +44,35 @@
<option name="hideEmptyMiddlePackages" value="true" /> <option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" /> <option name="showLibraryContents" value="true" />
</component> </component>
<component name="PropertiesComponent">{ <component name="PropertiesComponent"><![CDATA[{
&quot;keyToString&quot;: { "keyToString": {
&quot;ModuleVcsDetector.initialDetectionPerformed&quot;: &quot;true&quot;, "ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;, "ModuleVcsDetector.initialDetectionPerformed": "true",
&quot;RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252&quot;: &quot;true&quot;, "RunOnceActivity.ShowReadmeOnStart": "true",
&quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;, "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
&quot;com.intellij.ml.llm.matterhorn.ej.ui.settings.DefaultModelSelectionForGA.v1&quot;: &quot;true&quot;, "RunOnceActivity.git.unshallow": "true",
&quot;git-widget-placeholder&quot;: &quot;dev&quot;, "RunOnceActivity.typescript.service.memoryLimit.init": "true",
&quot;ignore.virus.scanning.warn.message&quot;: &quot;true&quot;, "SHARE_PROJECT_CONFIGURATION_FILES": "true",
&quot;js.debugger.nextJs.config.created.client&quot;: &quot;true&quot;, "com.intellij.ml.llm.matterhorn.ej.ui.settings.DefaultModelSelectionForGA.v1": "true",
&quot;js.debugger.nextJs.config.created.server&quot;: &quot;true&quot;, "git-widget-placeholder": "dev",
&quot;junie.onboarding.icon.badge.shown&quot;: &quot;true&quot;, "ignore.virus.scanning.warn.message": "true",
&quot;list.type.of.created.stylesheet&quot;: &quot;SCSS&quot;, "js.debugger.nextJs.config.created.client": "true",
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;, "js.debugger.nextJs.config.created.server": "true",
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;, "junie.onboarding.icon.badge.shown": "true",
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;, "list.type.of.created.stylesheet": "SCSS",
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;, "node.js.detected.package.eslint": "true",
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;, "node.js.detected.package.tslint": "true",
&quot;npm.Next.js: server-side.executor&quot;: &quot;Run&quot;, "node.js.selected.package.eslint": "(autodetect)",
&quot;prettierjs.PrettierConfiguration.Package&quot;: &quot;C:\\dev-personal\\ocenka-web\\node_modules\\prettier&quot;, "node.js.selected.package.tslint": "(autodetect)",
&quot;settings.editor.selected.configurable&quot;: &quot;terminal&quot;, "nodejs_package_manager_path": "npm",
&quot;to.speed.mode.migration.done&quot;: &quot;true&quot;, "npm.Next.js: server-side.executor": "Run",
&quot;ts.external.directory.path&quot;: &quot;C:\\dev-personal\\ocenka-web\\node_modules\\typescript\\lib&quot;, "prettierjs.PrettierConfiguration.Package": "C:\\dev-personal\\ocenka-web\\node_modules\\prettier",
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot; "settings.editor.selected.configurable": "terminal",
"to.speed.mode.migration.done": "true",
"ts.external.directory.path": "C:\\dev-personal\\ocenka-web\\node_modules\\typescript\\lib",
"vue.rearranger.settings.migration": "true"
} }
}</component> }]]></component>
<component name="RecentsManager"> <component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS"> <key name="MoveFile.RECENT_KEYS">
<recent name="C:\dev-personal\ocenka-web\public\images" /> <recent name="C:\dev-personal\ocenka-web\public\images" />
@@ -112,7 +99,7 @@
<component name="SharedIndexes"> <component name="SharedIndexes">
<attachedChunks> <attachedChunks>
<set> <set>
<option value="bundled-js-predefined-d6986cc7102b-a71380e98a7c-JavaScript-WS-252.28238.10" /> <option value="bundled-js-predefined-d6986cc7102b-c7e53b3be11b-JavaScript-WS-253.28294.332" />
</set> </set>
</attachedChunks> </attachedChunks>
</component> </component>
@@ -132,7 +119,8 @@
<workItem from="1764825390464" duration="26961000" /> <workItem from="1764825390464" duration="26961000" />
<workItem from="1765196288370" duration="332000" /> <workItem from="1765196288370" duration="332000" />
<workItem from="1765196704782" duration="4455000" /> <workItem from="1765196704782" duration="4455000" />
<workItem from="1765279298291" duration="3352000" /> <workItem from="1765279298291" duration="3813000" />
<workItem from="1765435962765" duration="3601000" />
</task> </task>
<servers /> <servers />
</component> </component>

View File

@@ -13,6 +13,19 @@ RUN npm install --frozen-lockfile
# Копируем все файлы проекта # Копируем все файлы проекта
COPY . . COPY . .
# Аргумент сборки для переменной окружения
ARG NEXT_PUBLIC_MAIL_USER
ARG NEXT_PUBLIC_MAIL_PASS
ARG NEXT_PUBLIC_MAIL_FROM
ARG NEXT_PUBLIC_MAIL_TO
ARG NEXT_PUBLIC_MAIL_SECURE_KEY
ENV NEXT_PUBLIC_MAIL_USER=$NEXT_PUBLIC_MAIL_USER \
NEXT_PUBLIC_MAIL_PASS=$NEXT_PUBLIC_MAIL_PASS \
NEXT_PUBLIC_MAIL_FROM=$NEXT_PUBLIC_MAIL_FROM \
NEXT_PUBLIC_MAIL_TO=$NEXT_PUBLIC_MAIL_TO \
NEXT_PUBLIC_MAIL_SECURE_KEY=$NEXT_PUBLIC_MAIL_SECURE_KEY
# Собираем приложение # Собираем приложение
RUN npm run build RUN npm run build
@@ -21,7 +34,12 @@ FROM node:22-alpine AS runner
WORKDIR /app WORKDIR /app
ENV NODE_ENV=production \ ENV NODE_ENV=production \
NEXT_TELEMETRY_DISABLED=1 NEXT_TELEMETRY_DISABLED=1 \
NEXT_PUBLIC_MAIL_USER=$NEXT_PUBLIC_MAIL_USER \
NEXT_PUBLIC_MAIL_PASS=$NEXT_PUBLIC_MAIL_PASS \
NEXT_PUBLIC_MAIL_FROM=$NEXT_PUBLIC_MAIL_FROM \
NEXT_PUBLIC_MAIL_TO=$NEXT_PUBLIC_MAIL_TO \
NEXT_PUBLIC_MAIL_SECURE_KEY=$NEXT_PUBLIC_MAIL_SECURE_KEY
# Включаем node пользователя # Включаем node пользователя
RUN addgroup -g 1001 -S nodejs RUN addgroup -g 1001 -S nodejs