feat: extract Directus sync/branding and optimize Gitea CI with Next.js lint support
This commit is contained in:
@@ -2,6 +2,9 @@ import js from "@eslint/js";
|
|||||||
import tseslint from "typescript-eslint";
|
import tseslint from "typescript-eslint";
|
||||||
|
|
||||||
export default tseslint.config(
|
export default tseslint.config(
|
||||||
|
{
|
||||||
|
ignores: ["**/dist/**", "**/node_modules/**", "**/.next/**"],
|
||||||
|
},
|
||||||
js.configs.recommended,
|
js.configs.recommended,
|
||||||
...tseslint.configs.recommended,
|
...tseslint.configs.recommended,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,15 +10,27 @@ const compat = new FlatCompat({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const nextConfig = [
|
export const nextConfig = [
|
||||||
|
{
|
||||||
|
ignores: [
|
||||||
|
"**/dist/**",
|
||||||
|
"**/.next/**",
|
||||||
|
"**/node_modules/**",
|
||||||
|
"**/.gitea/**",
|
||||||
|
"**/.changeset/**",
|
||||||
|
],
|
||||||
|
},
|
||||||
...compat.extends("next/core-web-vitals", "next/typescript"),
|
...compat.extends("next/core-web-vitals", "next/typescript"),
|
||||||
{
|
{
|
||||||
rules: {
|
rules: {
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
"@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }],
|
"@typescript-eslint/no-unused-vars": [
|
||||||
|
"warn",
|
||||||
|
{ argsIgnorePattern: "^_" },
|
||||||
|
],
|
||||||
"@typescript-eslint/no-require-imports": "off",
|
"@typescript-eslint/no-require-imports": "off",
|
||||||
"prefer-const": "warn",
|
"prefer-const": "warn",
|
||||||
"react/no-unescaped-entities": "off",
|
"react/no-unescaped-entities": "off",
|
||||||
"@next/next/no-img-element": "warn"
|
"@next/next/no-img-element": "warn",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export default {
|
const config = {
|
||||||
extends: ["@commitlint/config-conventional"],
|
extends: ["@commitlint/config-conventional"],
|
||||||
rules: {
|
rules: {
|
||||||
"header-max-length": [2, "always", 150],
|
"header-max-length": [2, "always", 150],
|
||||||
@@ -6,3 +6,5 @@ export default {
|
|||||||
"subject-full-stop": [0],
|
"subject-full-stop": [0],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
|
|||||||
@@ -1,4 +1,22 @@
|
|||||||
export default {
|
import path from "path";
|
||||||
"*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
|
|
||||||
|
const buildLintCommand = (filenames) => {
|
||||||
|
const isNext =
|
||||||
|
process.env.npm_package_devDependencies_next ||
|
||||||
|
process.env.npm_package_dependencies_next;
|
||||||
|
|
||||||
|
if (isNext) {
|
||||||
|
return `next lint --fix --file ${filenames
|
||||||
|
.map((f) => path.relative(process.cwd(), f))
|
||||||
|
.join(" --file ")}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "eslint --fix";
|
||||||
|
};
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
"*.{js,jsx,ts,tsx}": [buildLintCommand, "prettier --write"],
|
||||||
"*.{json,md,css,scss}": ["prettier --write"],
|
"*.{json,md,css,scss}": ["prettier --write"],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
|
|||||||
@@ -39,17 +39,23 @@ jobs:
|
|||||||
short_sha: ${{ steps.determine.outputs.short_sha }}
|
short_sha: ${{ steps.determine.outputs.short_sha }}
|
||||||
commit_msg: ${{ steps.determine.outputs.commit_msg }}
|
commit_msg: ${{ steps.determine.outputs.commit_msg }}
|
||||||
steps:
|
steps:
|
||||||
|
- name: 🧹 Maintenance (High Density Cleanup)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "Purging old build layers and dangling images..."
|
||||||
|
docker image prune -f
|
||||||
|
docker builder prune -f --filter "until=6h"
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 2
|
||||||
|
|
||||||
- name: 🔍 Environment & Version ermitteln
|
- name: 🔍 Environment & Version ermitteln
|
||||||
id: determine
|
id: determine
|
||||||
run: |
|
run: |
|
||||||
TAG="${{ github.ref_name }}"
|
TAG="${{ github.ref_name }}"
|
||||||
SHORT_SHA="${{ github.sha }}"
|
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-9)
|
||||||
SHORT_SHA="${SHORT_SHA:0:9}"
|
|
||||||
COMMIT_MSG=$(git log -1 --pretty=%s || echo "No commit message available")
|
COMMIT_MSG=$(git log -1 --pretty=%s || echo "No commit message available")
|
||||||
|
|
||||||
# Base Domain (e.g. example.com)
|
# Base Domain (e.g. example.com)
|
||||||
@@ -79,7 +85,6 @@ jobs:
|
|||||||
TARGET="production"
|
TARGET="production"
|
||||||
IMAGE_TAG="$TAG"
|
IMAGE_TAG="$TAG"
|
||||||
ENV_FILE=".env.prod"
|
ENV_FILE=".env.prod"
|
||||||
TRAEFIK_HOST="\${DOMAIN_BASE}, www.\${DOMAIN_BASE}" # Note: Host() backticks usually needed in compose
|
|
||||||
TRAEFIK_HOST="\`\${DOMAIN_BASE}\`, \`www.\${DOMAIN_BASE}\`"
|
TRAEFIK_HOST="\`\${DOMAIN_BASE}\`, \`www.\${DOMAIN_BASE}\`"
|
||||||
NEXT_PUBLIC_BASE_URL="https://\${DOMAIN_BASE}"
|
NEXT_PUBLIC_BASE_URL="https://\${DOMAIN_BASE}"
|
||||||
DIRECTUS_URL="https://cms.\${DOMAIN_BASE}"
|
DIRECTUS_URL="https://cms.\${DOMAIN_BASE}"
|
||||||
@@ -88,7 +93,7 @@ jobs:
|
|||||||
IS_PROD="true"
|
IS_PROD="true"
|
||||||
GOTIFY_TITLE="🚀 Production-Release"
|
GOTIFY_TITLE="🚀 Production-Release"
|
||||||
GOTIFY_PRIORITY=6
|
GOTIFY_PRIORITY=6
|
||||||
elif [[ "$TAG" =~ -rc\. || "$TAG" =~ -beta\. || "$TAG" =~ -alpha\. ]]; then
|
elif [[ "$TAG" =~ -rc || "$TAG" =~ -beta || "$TAG" =~ -alpha ]]; then
|
||||||
TARGET="staging"
|
TARGET="staging"
|
||||||
IMAGE_TAG="$TAG"
|
IMAGE_TAG="$TAG"
|
||||||
ENV_FILE=".env.staging"
|
ENV_FILE=".env.staging"
|
||||||
@@ -107,19 +112,21 @@ jobs:
|
|||||||
TARGET="skip"
|
TARGET="skip"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "target=$TARGET" >> $GITHUB_OUTPUT
|
{
|
||||||
echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT
|
echo "target=$TARGET"
|
||||||
echo "env_file=$ENV_FILE" >> $GITHUB_OUTPUT
|
echo "image_tag=$IMAGE_TAG"
|
||||||
echo "traefik_host=$TRAEFIK_HOST" >> $GITHUB_OUTPUT
|
echo "env_file=$ENV_FILE"
|
||||||
echo "next_public_base_url=$NEXT_PUBLIC_BASE_URL" >> $GITHUB_OUTPUT
|
echo "traefik_host=$TRAEFIK_HOST"
|
||||||
echo "directus_url=$DIRECTUS_URL" >> $GITHUB_OUTPUT
|
echo "next_public_base_url=$NEXT_PUBLIC_BASE_URL"
|
||||||
echo "directus_host=$DIRECTUS_HOST" >> $GITHUB_OUTPUT
|
echo "directus_url=$DIRECTUS_URL"
|
||||||
echo "project_name=$PROJECT_NAME" >> $GITHUB_OUTPUT
|
echo "directus_host=$DIRECTUS_HOST"
|
||||||
echo "is_prod=$IS_PROD" >> $GITHUB_OUTPUT
|
echo "project_name=$PROJECT_NAME"
|
||||||
echo "gotify_title=$GOTIFY_TITLE" >> $GITHUB_OUTPUT
|
echo "is_prod=$IS_PROD"
|
||||||
echo "gotify_priority=$GOTIFY_PRIORITY" >> $GITHUB_OUTPUT
|
echo "gotify_title=$GOTIFY_TITLE"
|
||||||
echo "short_sha=$SHORT_SHA" >> $GITHUB_OUTPUT
|
echo "gotify_priority=$GOTIFY_PRIORITY"
|
||||||
echo "commit_msg=$COMMIT_MSG" >> $GITHUB_OUTPUT
|
echo "short_sha=$SHORT_SHA"
|
||||||
|
echo "commit_msg=$COMMIT_MSG"
|
||||||
|
} >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────────
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
# JOB 2: Quality Assurance (Lint & Test)
|
# JOB 2: Quality Assurance (Lint & Test)
|
||||||
@@ -142,12 +149,19 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|
||||||
- name: 🧪 Run Checks
|
- name: 🧪 Run Checks in Parallel
|
||||||
if: github.event.inputs.skip_long_checks != 'true'
|
if: github.event.inputs.skip_long_checks != 'true'
|
||||||
run: |
|
run: |
|
||||||
npm run lint
|
npm run lint &
|
||||||
npm run typecheck
|
LINT_PID=$!
|
||||||
npm run test
|
npm run typecheck &
|
||||||
|
TYPE_PID=$!
|
||||||
|
npm run test &
|
||||||
|
TEST_PID=$!
|
||||||
|
|
||||||
|
wait $LINT_PID || exit 1
|
||||||
|
wait $TYPE_PID || exit 1
|
||||||
|
wait $TEST_PID || exit 1
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────────
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
# JOB 3: Build & Push
|
# JOB 3: Build & Push
|
||||||
@@ -161,6 +175,9 @@ jobs:
|
|||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 🐳 Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: 🔐 Registry Login
|
- name: 🔐 Registry Login
|
||||||
run: |
|
run: |
|
||||||
echo "${{ secrets.REGISTRY_PASS }}" | docker login registry.infra.mintel.me -u "${{ secrets.REGISTRY_USER }}" --password-stdin
|
echo "${{ secrets.REGISTRY_PASS }}" | docker login registry.infra.mintel.me -u "${{ secrets.REGISTRY_USER }}" --password-stdin
|
||||||
@@ -174,7 +191,10 @@ jobs:
|
|||||||
--pull \
|
--pull \
|
||||||
--platform linux/arm64 \
|
--platform linux/arm64 \
|
||||||
--build-arg NEXT_PUBLIC_BASE_URL="$NEXT_PUBLIC_BASE_URL" \
|
--build-arg NEXT_PUBLIC_BASE_URL="$NEXT_PUBLIC_BASE_URL" \
|
||||||
|
--build-arg NEXT_PUBLIC_TARGET="${{ needs.prepare.outputs.target }}" \
|
||||||
-t registry.infra.mintel.me/mintel/${{ github.event.repository.name }}:$IMAGE_TAG \
|
-t registry.infra.mintel.me/mintel/${{ github.event.repository.name }}:$IMAGE_TAG \
|
||||||
|
--cache-from type=registry,ref=registry.infra.mintel.me/mintel/${{ github.event.repository.name }}:buildcache \
|
||||||
|
--cache-to type=registry,ref=registry.infra.mintel.me/mintel/${{ github.event.repository.name }}:buildcache,mode=max \
|
||||||
--push .
|
--push .
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────────
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
@@ -187,16 +207,14 @@ jobs:
|
|||||||
runs-on: docker
|
runs-on: docker
|
||||||
env:
|
env:
|
||||||
TARGET: ${{ needs.prepare.outputs.target }}
|
TARGET: ${{ needs.prepare.outputs.target }}
|
||||||
|
IMAGE_TAG: ${{ needs.prepare.outputs.image_tag }}
|
||||||
|
PROJECT_NAME: ${{ needs.prepare.outputs.project_name }}
|
||||||
|
ENV_FILE: ${{ needs.prepare.outputs.env_file }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: 🚀 Deploy via SSH
|
- name: 🚀 Deploy via SSH
|
||||||
env:
|
|
||||||
IMAGE_TAG: ${{ needs.prepare.outputs.image_tag }}
|
|
||||||
ENV_FILE: ${{ needs.prepare.outputs.env_file }}
|
|
||||||
TRAEFIK_HOST: ${{ needs.prepare.outputs.traefik_host }}
|
|
||||||
PROJECT_NAME: ${{ needs.prepare.outputs.project_name }}
|
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ~/.ssh
|
mkdir -p ~/.ssh
|
||||||
echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_ed25519
|
echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_ed25519
|
||||||
@@ -208,12 +226,13 @@ jobs:
|
|||||||
# Generated by CI - $TARGET - $(date -u)
|
# Generated by CI - $TARGET - $(date -u)
|
||||||
NODE_ENV=production
|
NODE_ENV=production
|
||||||
IMAGE_TAG=$IMAGE_TAG
|
IMAGE_TAG=$IMAGE_TAG
|
||||||
TRAEFIK_HOST=$TRAEFIK_HOST
|
TRAEFIK_HOST=${{ needs.prepare.outputs.traefik_host }}
|
||||||
PROJECT_NAME=$PROJECT_NAME
|
PROJECT_NAME=$PROJECT_NAME
|
||||||
ENV_FILE=$ENV_FILE
|
ENV_FILE=$ENV_FILE
|
||||||
|
|
||||||
# App Config
|
# App Config
|
||||||
NEXT_PUBLIC_BASE_URL=${{ needs.prepare.outputs.next_public_base_url }}
|
NEXT_PUBLIC_BASE_URL=${{ needs.prepare.outputs.next_public_base_url }}
|
||||||
|
NEXT_PUBLIC_TARGET=$TARGET
|
||||||
|
|
||||||
# Directus Config
|
# Directus Config
|
||||||
DIRECTUS_URL=${{ needs.prepare.outputs.directus_url }}
|
DIRECTUS_URL=${{ needs.prepare.outputs.directus_url }}
|
||||||
@@ -237,10 +256,11 @@ jobs:
|
|||||||
ssh root@${{ secrets.SSH_HOST }} IMAGE_TAG="$IMAGE_TAG" ENV_FILE="$ENV_FILE" PROJECT_NAME="$PROJECT_NAME" bash << 'EOF'
|
ssh root@${{ secrets.SSH_HOST }} IMAGE_TAG="$IMAGE_TAG" ENV_FILE="$ENV_FILE" PROJECT_NAME="$PROJECT_NAME" bash << 'EOF'
|
||||||
set -e
|
set -e
|
||||||
cd "/home/deploy/sites/${{ github.event.repository.name }}"
|
cd "/home/deploy/sites/${{ github.event.repository.name }}"
|
||||||
|
chmod 600 "$ENV_FILE"
|
||||||
echo "${{ secrets.REGISTRY_PASS }}" | docker login registry.infra.mintel.me -u "${{ secrets.REGISTRY_USER }}" --password-stdin
|
echo "${{ secrets.REGISTRY_PASS }}" | docker login registry.infra.mintel.me -u "${{ secrets.REGISTRY_USER }}" --password-stdin
|
||||||
docker compose -p "$PROJECT_NAME" --env-file "$ENV_FILE" pull
|
docker compose -p "$PROJECT_NAME" --env-file "$ENV_FILE" pull
|
||||||
docker compose -p "$PROJECT_NAME" --env-file "$ENV_FILE" up -d --remove-orphans
|
docker compose -p "$PROJECT_NAME" --env-file "$ENV_FILE" up -d --remove-orphans
|
||||||
docker system prune -f --filter "until=168h"
|
docker system prune -f --filter "until=24h"
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────────
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
@@ -252,10 +272,22 @@ jobs:
|
|||||||
if: always()
|
if: always()
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
steps:
|
steps:
|
||||||
- name: 🔔 Gotify
|
- name: 🔔 Gotify - Success
|
||||||
if: needs.deploy.result == 'success'
|
if: needs.deploy.result == 'success'
|
||||||
run: |
|
run: |
|
||||||
curl -s -k -X POST "${{ secrets.GOTIFY_URL }}/message?token=${{ secrets.GOTIFY_TOKEN }}" \
|
curl -s -k -X POST "${{ secrets.GOTIFY_URL }}/message?token=${{ secrets.GOTIFY_TOKEN }}" \
|
||||||
-F "title=${{ needs.prepare.outputs.gotify_title }}" \
|
-F "title=${{ needs.prepare.outputs.gotify_title }}" \
|
||||||
-F "message=Erfolgreich deployt auf **${{ needs.prepare.outputs.target }}**" \
|
-F "message=Erfolgreich deployt auf **${{ needs.prepare.outputs.target }}**\n\nVersion: **${{ needs.prepare.outputs.image_tag }}**\nCommit: ${{ needs.prepare.outputs.short_sha }}\nRun: ${{ github.run_id }}" \
|
||||||
-F "priority=4" || true
|
-F "priority=4" || true
|
||||||
|
|
||||||
|
- name: 🔔 Gotify - Failure
|
||||||
|
if: |
|
||||||
|
needs.prepare.result == 'failure' ||
|
||||||
|
needs.qa.result == 'failure' ||
|
||||||
|
needs.build.result == 'failure' ||
|
||||||
|
needs.deploy.result == 'failure'
|
||||||
|
run: |
|
||||||
|
curl -s -k -X POST "${{ secrets.GOTIFY_URL }}/message?token=${{ secrets.GOTIFY_TOKEN }}" \
|
||||||
|
-F "title=❌ Deployment FEHLGESCHLAGEN – ${{ github.event.repository.name }}" \
|
||||||
|
-F "message=**Fehler beim Deploy auf ${{ needs.prepare.outputs.target || 'unknown' }}**\n\nRun: ${{ github.run_id }}\nBitte Logs prüfen!" \
|
||||||
|
-F "priority=8" || true
|
||||||
|
|||||||
68
packages/infra/scripts/sync-directus.sh
Normal file
68
packages/infra/scripts/sync-directus.sh
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Mintel Directus Sync Engine
|
||||||
|
# Synchronizes Directus Data (Postgres + Uploads) between Local and Remote
|
||||||
|
|
||||||
|
REMOTE_HOST="${SSH_HOST:-root@alpha.mintel.me}"
|
||||||
|
ACTION=$1
|
||||||
|
ENV=$2
|
||||||
|
|
||||||
|
# Help
|
||||||
|
if [ -z "$ACTION" ] || [ -z "$ENV" ]; then
|
||||||
|
echo "Usage: mintel-sync [push|pull] [testing|staging|production]"
|
||||||
|
echo ""
|
||||||
|
echo "Commands:"
|
||||||
|
echo " push Sync LOCAL data -> REMOTE"
|
||||||
|
echo " pull Sync REMOTE data -> LOCAL"
|
||||||
|
echo ""
|
||||||
|
echo "Environments:"
|
||||||
|
echo " testing, staging, production"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PRJ_ID=$(jq -r .name package.json | sed 's/@mintel\///')
|
||||||
|
case $ENV in
|
||||||
|
testing) PROJECT_NAME="${PRJ_ID}-testing"; ENV_FILE=".env.testing" ;;
|
||||||
|
staging) PROJECT_NAME="${PRJ_ID}-staging"; ENV_FILE=".env.staging" ;;
|
||||||
|
production) PROJECT_NAME="${PRJ_ID}-prod"; ENV_FILE=".env.prod" ;;
|
||||||
|
*) echo "❌ Invalid environment: $ENV"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
REMOTE_DIR="/home/deploy/sites/${PRJ_ID}.com"
|
||||||
|
|
||||||
|
# DB Details
|
||||||
|
DB_USER="directus"
|
||||||
|
DB_NAME="directus"
|
||||||
|
|
||||||
|
echo "🔍 Detecting local database..."
|
||||||
|
LOCAL_DB_CONTAINER=$(docker compose ps -q directus-db)
|
||||||
|
if [ -z "$LOCAL_DB_CONTAINER" ]; then
|
||||||
|
echo "❌ Local directus-db container not found. Running?"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$ACTION" == "push" ]; then
|
||||||
|
echo "🚀 Pushing LOCAL -> $ENV ($PROJECT_NAME)..."
|
||||||
|
docker exec "$LOCAL_DB_CONTAINER" pg_dump -U "$DB_USER" --clean --if-exists --no-owner --no-privileges "$DB_NAME" > dump.sql
|
||||||
|
scp dump.sql "$REMOTE_HOST:$REMOTE_DIR/dump.sql"
|
||||||
|
|
||||||
|
REMOTE_DB_CONTAINER=$(ssh "$REMOTE_HOST" "cd $REMOTE_DIR && docker compose -p $PROJECT_NAME ps -q directus-db")
|
||||||
|
ssh "$REMOTE_HOST" "docker exec -i $REMOTE_DB_CONTAINER psql -U $DB_USER $DB_NAME < $REMOTE_DIR/dump.sql"
|
||||||
|
|
||||||
|
rsync -avz --progress ./directus/uploads/ "$REMOTE_HOST:$REMOTE_DIR/directus/uploads/"
|
||||||
|
rm dump.sql
|
||||||
|
ssh "$REMOTE_HOST" "rm $REMOTE_DIR/dump.sql"
|
||||||
|
echo "✨ Push complete!"
|
||||||
|
|
||||||
|
elif [ "$ACTION" == "pull" ]; then
|
||||||
|
echo "📥 Pulling $ENV -> LOCAL..."
|
||||||
|
REMOTE_DB_CONTAINER=$(ssh "$REMOTE_HOST" "cd $REMOTE_DIR && docker compose -p $PROJECT_NAME ps -q directus-db")
|
||||||
|
ssh "$REMOTE_HOST" "docker exec $REMOTE_DB_CONTAINER pg_dump -U $DB_USER --clean --if-exists --no-owner --no-privileges $DB_NAME > $REMOTE_DIR/dump.sql"
|
||||||
|
scp "$REMOTE_HOST:$REMOTE_DIR/dump.sql" dump.sql
|
||||||
|
|
||||||
|
docker exec -i "$LOCAL_DB_CONTAINER" psql -U "$DB_USER" "$DB_NAME" < dump.sql
|
||||||
|
rsync -avz --progress "$REMOTE_HOST:$REMOTE_DIR/directus/uploads/" ./directus/uploads/
|
||||||
|
rm dump.sql
|
||||||
|
ssh "$REMOTE_HOST" "rm $REMOTE_DIR/dump.sql"
|
||||||
|
echo "✨ Pull complete!"
|
||||||
|
fi
|
||||||
@@ -1,18 +1,46 @@
|
|||||||
import client, { ensureAuthenticated } from "../src/lib/directus";
|
import {
|
||||||
|
createMintelDirectusClient,
|
||||||
|
ensureDirectusAuthenticated,
|
||||||
|
} from "@mintel/next-utils";
|
||||||
import { updateSettings } from "@directus/sdk";
|
import { updateSettings } from "@directus/sdk";
|
||||||
|
|
||||||
|
const client = createMintelDirectusClient();
|
||||||
|
|
||||||
async function setupBranding() {
|
async function setupBranding() {
|
||||||
console.log("🎨 Setup Directus Branding...");
|
const prjName = process.env.PROJECT_NAME || "Mintel Project";
|
||||||
await ensureAuthenticated();
|
const prjColor = process.env.PROJECT_COLOR || "#82ed20";
|
||||||
|
|
||||||
|
console.log(`🎨 Setup Directus Branding for ${prjName}...`);
|
||||||
|
await ensureDirectusAuthenticated(client);
|
||||||
|
|
||||||
|
const cssInjection = `
|
||||||
|
<style>
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
||||||
|
body, .v-app { font-family: 'Inter', sans-serif !important; }
|
||||||
|
.public-view .v-card {
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
border-radius: 32px !important;
|
||||||
|
box-shadow: 0 50px 100px -20px rgba(0, 0, 0, 0.4) !important;
|
||||||
|
}
|
||||||
|
.v-navigation-drawer { background: #000c24 !important; }
|
||||||
|
</style>
|
||||||
|
<div style="font-family: 'Inter', sans-serif; text-align: center; margin-top: 24px;">
|
||||||
|
<p style="color: rgba(255,255,255,0.7); font-size: 14px; margin-bottom: 4px; font-weight: 500;">MINTEL INFRASTRUCTURE ENGINE</p>
|
||||||
|
<h1 style="color: #ffffff; font-size: 18px; font-weight: 700; margin: 0;">${prjName.toUpperCase()} <span style="color: ${prjColor};">RELIABILITY.</span></h1>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await client.request(
|
await client.request(
|
||||||
updateSettings({
|
updateSettings({
|
||||||
project_name: process.env.PROJECT_NAME || "Mintel Project",
|
project_name: prjName,
|
||||||
project_color: process.env.PROJECT_COLOR || "#82ed20",
|
project_color: prjColor,
|
||||||
|
public_note: cssInjection,
|
||||||
theme_light_overrides: {
|
theme_light_overrides: {
|
||||||
primary: process.env.PROJECT_COLOR || "#82ed20",
|
primary: prjColor,
|
||||||
borderRadius: "16px",
|
borderRadius: "16px",
|
||||||
|
navigationBackground: "#000c24",
|
||||||
|
navigationForeground: "#ffffff",
|
||||||
},
|
},
|
||||||
} as any),
|
} as any),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,38 +1,41 @@
|
|||||||
import createNextIntlPlugin from 'next-intl/plugin';
|
import createNextIntlPlugin from "next-intl/plugin";
|
||||||
import { withSentryConfig } from '@sentry/nextjs';
|
import { withSentryConfig } from "@sentry/nextjs";
|
||||||
|
|
||||||
const withNextIntl = createNextIntlPlugin();
|
const withNextIntl = createNextIntlPlugin();
|
||||||
|
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
export const baseNextConfig = {
|
export const baseNextConfig = {
|
||||||
output: 'standalone',
|
output: "standalone",
|
||||||
images: {
|
images: {
|
||||||
dangerouslyAllowSVG: true,
|
dangerouslyAllowSVG: true,
|
||||||
contentDispositionType: 'attachment',
|
contentDispositionType: "attachment",
|
||||||
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
|
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
|
||||||
},
|
},
|
||||||
async rewrites() {
|
async rewrites() {
|
||||||
const umamiUrl = (process.env.NEXT_PUBLIC_UMAMI_SCRIPT_URL || 'https://analytics.infra.mintel.me').replace('/script.js', '');
|
const umamiUrl = (
|
||||||
|
process.env.NEXT_PUBLIC_UMAMI_SCRIPT_URL ||
|
||||||
|
"https://analytics.infra.mintel.me"
|
||||||
|
).replace("/script.js", "");
|
||||||
const glitchtipUrl = process.env.SENTRY_DSN
|
const glitchtipUrl = process.env.SENTRY_DSN
|
||||||
? new URL(process.env.SENTRY_DSN).origin
|
? new URL(process.env.SENTRY_DSN).origin
|
||||||
: 'https://errors.infra.mintel.me';
|
: "https://errors.infra.mintel.me";
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
source: '/stats/:path*',
|
source: "/stats/:path*",
|
||||||
destination: `${umamiUrl}/:path*`,
|
destination: `${umamiUrl}/:path*`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
source: '/errors/:path*',
|
source: "/errors/:path*",
|
||||||
destination: `${glitchtipUrl}/:path*`,
|
destination: `${glitchtipUrl}/:path*`,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (config) => {
|
const withMintelConfig = (config) => {
|
||||||
const nextIntlConfig = withNextIntl({ ...baseNextConfig, ...config });
|
const nextIntlConfig = withNextIntl({ ...baseNextConfig, ...config });
|
||||||
|
|
||||||
return withSentryConfig(
|
return withSentryConfig(
|
||||||
nextIntlConfig,
|
nextIntlConfig,
|
||||||
{
|
{
|
||||||
@@ -41,6 +44,8 @@ export default (config) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
authToken: undefined,
|
authToken: undefined,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default withMintelConfig;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import { execSync } from "child_process";
|
|
||||||
|
|
||||||
const tag = process.env.GITHUB_REF_NAME || process.env.TAG;
|
const tag = process.env.GITHUB_REF_NAME || process.env.TAG;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user