Compare commits

...

13 Commits

Author SHA1 Message Date
b9fd583ac4 chore: fix pipeline hang by disabling broken caching and using corepack
Some checks failed
Monorepo Pipeline / ⚡ Prioritize Release (push) Successful in 1s
Monorepo Pipeline / 🧹 Lint (push) Successful in 57s
Monorepo Pipeline / 🚀 Release (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Directus (Base) (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been cancelled
Monorepo Pipeline / 🧪 Test (push) Has been cancelled
Monorepo Pipeline / 🏗️ Build (push) Has been cancelled
2026-02-11 00:29:10 +01:00
bfdbaba0d0 chore: implement release prioritization and streamline setup for speed
Some checks failed
Monorepo Pipeline / ⚡ Prioritize Release (push) Successful in 2s
Monorepo Pipeline / 🧹 Lint (push) Successful in 1m2s
Monorepo Pipeline / 🧪 Test (push) Successful in 58s
Monorepo Pipeline / 🚀 Release (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Directus (Base) (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been cancelled
Monorepo Pipeline / 🏗️ Build (push) Has been cancelled
2026-02-11 00:22:31 +01:00
4ea9cbc551 fix(next-utils): use natural type inference for validateMintelEnv to fix unknown type errors
Some checks failed
Monorepo Pipeline / 🚀 Release (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Directus (Base) (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been cancelled
Monorepo Pipeline / 🏗️ Build (push) Has been cancelled
Monorepo Pipeline / 🧹 Lint (push) Has been cancelled
Monorepo Pipeline / 🧪 Test (push) Has been cancelled
Monorepo Pipeline / 📦 Install & Sync (push) Has been cancelled
2026-02-11 00:17:46 +01:00
d8c1a38c0d chore: optimize pipeline for speed and parallelize QA jobs
Some checks failed
Monorepo Pipeline / 🧹 Lint (push) Has been cancelled
Monorepo Pipeline / 🧪 Test (push) Has been cancelled
Monorepo Pipeline / 🏗️ Build (push) Has been cancelled
Monorepo Pipeline / 🚀 Release (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Directus (Base) (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been cancelled
Monorepo Pipeline / 📦 Install & Sync (push) Has been cancelled
2026-02-11 00:14:55 +01:00
b65b9a7fb2 fix(next-utils): finalize type safety for validateMintelEnv and fix pre-push hook
Some checks failed
Monorepo Pipeline / 🧪 Quality Assurance (push) Failing after 2m7s
Monorepo Pipeline / 🚀 Release (push) Has been skipped
Monorepo Pipeline / 🐳 Build Directus (Base) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been skipped
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been skipped
2026-02-11 00:10:38 +01:00
858c7bbc39 fix(next-utils): use z.extend() for robust type inference in validateMintelEnv
Some checks failed
Monorepo Pipeline / 🧪 Quality Assurance (push) Successful in 2m33s
Monorepo Pipeline / 🐳 Build Directus (Base) (push) Successful in 33s
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been cancelled
Monorepo Pipeline / 🚀 Release (push) Has been cancelled
2026-02-11 00:04:14 +01:00
149123ef90 fix(next-utils): restore optional argument with robust types to satisfy linter
Some checks failed
Monorepo Pipeline / 🚀 Release (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Directus (Base) (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been cancelled
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been cancelled
Monorepo Pipeline / 🧪 Quality Assurance (push) Has been cancelled
2026-02-11 00:02:53 +01:00
6bc49d1c52 fix(next-utils): make validateMintelEnv generic for better type safety
Some checks failed
Monorepo Pipeline / 🧪 Quality Assurance (push) Failing after 2m58s
Monorepo Pipeline / 🚀 Release (push) Has been skipped
Monorepo Pipeline / 🐳 Build Directus (Base) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been skipped
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been skipped
2026-02-10 23:57:18 +01:00
52ffe49019 feat(next-utils): make directus client environment-aware and standardize base env schema
All checks were successful
Monorepo Pipeline / 🧪 Quality Assurance (push) Successful in 2m10s
Monorepo Pipeline / 🚀 Release (push) Has been skipped
Monorepo Pipeline / 🐳 Build Directus (Base) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been skipped
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been skipped
2026-02-10 23:44:27 +01:00
73fa292528 fix: remove klz from workspace 2026-02-10 21:39:48 +01:00
f2c0a4581c chore: sync versions
All checks were successful
Monorepo Pipeline / 🧪 Quality Assurance (push) Successful in 2m6s
Monorepo Pipeline / 🚀 Release (push) Has been skipped
Monorepo Pipeline / 🐳 Build Directus (Base) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been skipped
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been skipped
2026-02-10 00:39:34 +01:00
367c4d8404 fix: cms schema 2026-02-10 00:35:26 +01:00
587c88980f chore: release next-config v1.7.0
All checks were successful
Monorepo Pipeline / 🧪 Quality Assurance (push) Successful in 2m8s
Monorepo Pipeline / 🚀 Release (push) Successful in 1m51s
Monorepo Pipeline / 🐳 Build Directus (Base) (push) Successful in 17s
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Successful in 2m18s
Monorepo Pipeline / 🐳 Build Production Runtime (push) Successful in 16s
Monorepo Pipeline / 🐳 Build Build-Base (push) Successful in 5m34s
2026-02-10 00:29:02 +01:00
28 changed files with 224 additions and 77 deletions

View File

@@ -1,4 +1,5 @@
# Project
IMAGE_TAG=v1.7.3
PROJECT_NAME=sample-website
PROJECT_COLOR=#82ed20

View File

@@ -12,8 +12,35 @@ concurrency:
cancel-in-progress: true
jobs:
qa:
name: 🧪 Quality Assurance
prioritize:
name: ⚡ Prioritize Release
runs-on: docker
container:
image: catthehacker/ubuntu:act-latest
steps:
- name: 🛑 Cancel Redundant Runs
if: startsWith(github.ref, 'refs/tags/v')
env:
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
RUN_ID: ${{ github.run_id }}
run: |
echo "🚀 Release detected. Cancelling non-tag runs..."
# Get all runs for this repo
RUNS=$(curl -s -H "Authorization: token $GITEA_TOKEN" "https://git.infra.mintel.me/api/v1/repos/$REPO/actions/runs")
# Iterate and cancel in_progress/queued non-tag runs
echo "$RUNS" | jq -c '.workflow_runs[] | select(.status == "in_progress" or .status == "queued") | select(.id | tostring != "'$RUN_ID'") | select(.event != "push" or .ref | contains("refs/tags/v") | not)' | while read run; do
ID=$(echo "$run" | jq -r '.id')
DESC=$(echo "$run" | jq -r '.display_title')
echo "🛑 Cancelling redundant run $ID ($DESC)..."
curl -X POST -s -H "Authorization: token $GITEA_TOKEN" "https://git.infra.mintel.me/api/v1/repos/$REPO/actions/runs/$ID/cancel"
done
lint:
name: 🧹 Lint
needs: prioritize
if: always() && !cancelled() && (needs.prioritize.result == 'success' || needs.prioritize.result == 'skipped')
runs-on: docker
container:
image: catthehacker/ubuntu:act-latest
@@ -22,36 +49,66 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node_version: 20
- name: Enable pnpm
run: corepack enable && corepack prepare pnpm@10.2.0 --activate
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: 🏷️ Sync Versions (if Tagged)
if: startsWith(github.ref, 'refs/tags/v')
run: pnpm sync-versions
run: pnpm install --frozen-lockfile --prefer-offline --ignore-scripts --no-color
- name: Lint
run: pnpm lint
test:
name: 🧪 Test
needs: prioritize
if: always() && !cancelled() && (needs.prioritize.result == 'success' || needs.prioritize.result == 'skipped')
runs-on: docker
container:
image: catthehacker/ubuntu:act-latest
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node_version: 20
- name: Enable pnpm
run: corepack enable && corepack prepare pnpm@10.2.0 --activate
- name: Install dependencies
run: pnpm install --frozen-lockfile --prefer-offline --ignore-scripts --no-color
- name: Test
run: pnpm test
build:
name: 🏗️ Build
needs: prioritize
if: always() && !cancelled() && (needs.prioritize.result == 'success' || needs.prioritize.result == 'skipped')
runs-on: docker
container:
image: catthehacker/ubuntu:act-latest
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node_version: 20
- name: Enable pnpm
run: corepack enable && corepack prepare pnpm@10.2.0 --activate
- name: Install dependencies
run: pnpm install --frozen-lockfile --prefer-offline --ignore-scripts --no-color
- name: Build
run: pnpm build
release:
name: 🚀 Release
needs: qa
needs: [lint, test, build]
if: startsWith(github.ref, 'refs/tags/v')
runs-on: docker
container:
@@ -64,20 +121,16 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node_version: 20
- name: Enable pnpm
run: corepack enable && corepack prepare pnpm@10.2.0 --activate
- name: Install dependencies
run: pnpm install --frozen-lockfile
run: pnpm install --frozen-lockfile --prefer-offline --ignore-scripts --no-color
- name: 🏷️ Sync Versions (if Tagged)
run: pnpm sync-versions
- name: 🏷️ Release Packages (Tag-Driven)
run: |
echo "🏷️ Tag detected [${{ github.ref_name }}], performing sync release..."
@@ -85,7 +138,7 @@ jobs:
build-images:
name: 🐳 Build ${{ matrix.name }}
needs: qa
needs: [lint, test, build]
if: startsWith(github.ref, 'refs/tags/v')
runs-on: docker
container:

View File

@@ -1,13 +1,16 @@
# Check if we are pushing a tag
if echo "$*" | grep -q "refs/tags/v"; then
echo "🏷️ Tag detected in push, syncing versions..."
pnpm sync-versions
# Stage the changed package.json files
git add "package.json" "packages/*/package.json" "apps/*/package.json"
# Amend the tag if it's on the current commit, but this is complex in pre-push.
# Better: Just warn the user that they might need to update the tag if package.json changed.
echo "⚠️ package.json files updated to match tag. Please ensure these changes are part of your tag/commit."
fi
while read local_ref local_sha remote_ref remote_sha
do
if [[ "$remote_ref" == refs/tags/v* ]]; then
TAG=${remote_ref#refs/tags/}
echo "🏷️ Tag detected: $TAG, syncing versions..."
pnpm sync-versions "$TAG"
# Stage the changed files (excluding ignored files like .env)
git add package.json packages/*/package.json apps/*/package.json .env.example
echo "⚠️ package.json and .env files updated to match tag $TAG."
echo "⚠️ Note: You might need to push again if these changes were not already in your commit/tag."
fi
done

View File

@@ -1,6 +1,6 @@
{
"name": "sample-website",
"version": "1.6.0",
"version": "1.7.3",
"private": true,
"type": "module",
"scripts": {

View File

@@ -23,7 +23,7 @@ services:
- "traefik.http.services.sample-website.loadbalancer.server.port=3000"
directus:
image: registry.infra.mintel.me/mintel/directus:latest
image: registry.infra.mintel.me/mintel/directus:${IMAGE_TAG:-latest}
restart: always
networks:
- infra

View File

@@ -9,7 +9,7 @@
"test": "pnpm -r test",
"changeset": "changeset",
"version-packages": "changeset version",
"sync-versions": "tsx scripts/sync-versions.ts",
"sync-versions": "tsx scripts/sync-versions.ts --",
"cms:push:infra": "./scripts/sync-directus.sh push infra",
"cms:pull:infra": "./scripts/sync-directus.sh pull infra",
"cms:schema:snapshot": "./scripts/cms-snapshot.sh",
@@ -52,7 +52,7 @@
"pino-pretty": "^13.1.3",
"require-in-the-middle": "^8.0.1"
},
"version": "1.6.0",
"version": "1.7.3",
"pnpm": {
"overrides": {
"next": "16.1.6",

View File

@@ -1,6 +1,6 @@
{
"name": "@mintel/cli",
"version": "1.6.0",
"version": "1.7.3",
"publishConfig": {
"access": "public",
"registry": "https://npm.infra.mintel.me"

Binary file not shown.

View File

@@ -1,6 +1,6 @@
{
"name": "@mintel/cms-infra",
"version": "1.6.0",
"version": "1.7.3",
"private": true,
"type": "module",
"scripts": {

View File

@@ -910,7 +910,7 @@ fields:
foreign_key_column: null
- collection: visual_feedback
field: screenshot
type: string
type: uuid
meta:
collection: visual_feedback
conditions: null
@@ -1111,6 +1111,24 @@ fields:
has_auto_increment: false
foreign_key_table: null
foreign_key_column: null
- collection: visual_feedback_comments
field: feedback_id
type: integer
meta:
collection: visual_feedback_comments
field: feedback_id
interface: select-dropdown-m2o
special: null
width: full
required: true
schema:
name: feedback_id
table: visual_feedback_comments
data_type: integer
is_nullable: false
is_indexed: true
foreign_key_table: visual_feedback
foreign_key_column: id
systemFields:
- collection: directus_activity
field: timestamp

View File

@@ -2,7 +2,7 @@
"name": "customer-manager",
"description": "Custom High-Fidelity Customer & Company Management for Directus",
"icon": "supervisor_account",
"version": "1.6.0",
"version": "1.7.3",
"keywords": [
"directus",
"directus-extension",

View File

@@ -1,6 +1,6 @@
{
"name": "@mintel/eslint-config",
"version": "1.6.0",
"version": "1.7.3",
"publishConfig": {
"access": "public",
"registry": "https://npm.infra.mintel.me"

View File

@@ -2,7 +2,7 @@
"name": "@mintel/extension-feedback-commander",
"description": "Custom High-Fidelity Feedback Management Extension for Directus",
"icon": "view_kanban",
"version": "1.6.0",
"version": "1.7.3",
"keywords": [
"directus",
"directus-extension",

View File

@@ -1,6 +1,6 @@
{
"name": "@mintel/gatekeeper",
"version": "1.6.0",
"version": "1.7.3",
"private": true,
"type": "module",
"scripts": {

View File

@@ -1,6 +1,6 @@
{
"name": "@mintel/husky-config",
"version": "1.6.0",
"version": "1.7.3",
"publishConfig": {
"access": "public",
"registry": "https://npm.infra.mintel.me"

View File

@@ -53,7 +53,7 @@ services:
- "traefik.http.services.${PROJECT_NAME}-gatekeeper.loadbalancer.server.port=3000"
directus:
image: registry.infra.mintel.me/mintel/directus:latest
image: registry.infra.mintel.me/mintel/directus:${IMAGE_TAG:-latest}
restart: always
networks:
- infra

View File

@@ -1,6 +1,6 @@
{
"name": "@mintel/infra",
"version": "1.6.0",
"version": "1.7.3",
"publishConfig": {
"access": "public",
"registry": "https://npm.infra.mintel.me"

View File

@@ -1,6 +1,6 @@
{
"name": "@mintel/mail",
"version": "1.7.0",
"version": "1.7.3",
"private": false,
"publishConfig": {
"access": "public",

View File

@@ -1,6 +1,6 @@
{
"name": "@mintel/next-config",
"version": "1.6.1",
"version": "1.7.3",
"publishConfig": {
"access": "public",
"registry": "https://npm.infra.mintel.me"

View File

@@ -1,6 +1,6 @@
{
"name": "@mintel/next-feedback",
"version": "1.6.0",
"version": "1.7.3",
"publishConfig": {
"access": "public",
"registry": "https://npm.infra.mintel.me"

View File

@@ -1,6 +1,6 @@
{
"name": "@mintel/next-observability",
"version": "1.6.0",
"version": "1.7.3",
"publishConfig": {
"access": "public",
"registry": "https://npm.infra.mintel.me"

View File

@@ -1,6 +1,6 @@
{
"name": "@mintel/next-utils",
"version": "1.6.0",
"version": "1.7.7",
"publishConfig": {
"access": "public",
"registry": "https://npm.infra.mintel.me"

View File

@@ -12,13 +12,35 @@ export type MintelDirectusClient = DirectusClient<any> &
AuthenticationClient<any>;
/**
* Creates a Directus client configured with Mintel standards
* Creates a Directus client configured with Mintel standards.
* Automatically handles internal vs. external URLs based on environment.
*/
export function createMintelDirectusClient(url?: string): MintelDirectusClient {
const directusUrl =
url || process.env.DIRECTUS_URL || "http://localhost:8055";
const isServer = typeof window === "undefined";
return createDirectus(directusUrl).with(rest()).with(authentication());
// 1. If an explicit URL is provided, use it.
if (url) {
return createDirectus(url).with(rest()).with(authentication());
}
// 2. On server: Prioritize INTERNAL_DIRECTUS_URL, fallback to DIRECTUS_URL
if (isServer) {
const directusUrl =
process.env.INTERNAL_DIRECTUS_URL ||
process.env.DIRECTUS_URL ||
"http://localhost:8055";
return createDirectus(directusUrl).with(rest()).with(authentication());
}
// 3. In browser: Use a proxy path if we are on a different origin,
// or use the current origin if no DIRECTUS_URL is set.
const proxyPath = "/api/directus"; // Standard Mintel proxy path
const browserUrl =
typeof window !== "undefined"
? `${window.location.origin}${proxyPath}`
: proxyPath;
return createDirectus(browserUrl).with(rest()).with(authentication());
}
/**

View File

@@ -4,10 +4,17 @@ export const mintelEnvSchema = {
NODE_ENV: z
.enum(["development", "production", "test"])
.default("development"),
NEXT_PUBLIC_BASE_URL: z.string().url(),
NEXT_PUBLIC_BASE_URL: z.string().url().optional(),
NEXT_PUBLIC_TARGET: z
.enum(["development", "testing", "staging", "production"])
.optional(),
TARGET: z
.enum(["development", "testing", "staging", "production"])
.optional(),
// Analytics (Proxy Pattern)
UMAMI_WEBSITE_ID: z.string().optional(),
NEXT_PUBLIC_UMAMI_WEBSITE_ID: z.string().optional(),
UMAMI_API_ENDPOINT: z
.string()
.url()
@@ -23,6 +30,8 @@ export const mintelEnvSchema = {
LOG_LEVEL: z
.enum(["trace", "debug", "info", "warn", "error", "fatal"])
.default("info"),
// Mail
MAIL_HOST: z.string().optional(),
MAIL_PORT: z.coerce.number().default(587),
MAIL_USERNAME: z.string().optional(),
@@ -32,13 +41,19 @@ export const mintelEnvSchema = {
(val) => (typeof val === "string" ? val.split(",").filter(Boolean) : val),
z.array(z.string()).default([]),
),
// Directus
DIRECTUS_URL: z.string().url().default("http://localhost:8055"),
DIRECTUS_ADMIN_EMAIL: z.string().optional(),
DIRECTUS_ADMIN_PASSWORD: z.string().optional(),
DIRECTUS_API_TOKEN: z.string().optional(),
INTERNAL_DIRECTUS_URL: z.string().url().optional(),
};
export function validateMintelEnv(schemaExtension = {}) {
const fullSchema = z.object({
...mintelEnvSchema,
...schemaExtension,
});
export function validateMintelEnv<
T extends z.ZodRawShape = Record<string, never>,
>(schemaExtension: T = {} as T) {
const fullSchema = z.object(mintelEnvSchema).extend(schemaExtension);
const isBuildTime =
process.env.NEXT_PHASE === "phase-production-build" ||
@@ -51,7 +66,7 @@ export function validateMintelEnv(schemaExtension = {}) {
console.warn(
"⚠️ Some environment variables are missing during build, but skipping strict validation.",
);
// Return partial data to allow build to continue
// Return process.env casted to the full schema type to unblock builds
return process.env as unknown as z.infer<typeof fullSchema>;
}

View File

@@ -1,6 +1,6 @@
{
"name": "@mintel/observability",
"version": "1.6.0",
"version": "1.7.3",
"publishConfig": {
"access": "public",
"registry": "https://npm.infra.mintel.me"

View File

@@ -1,6 +1,6 @@
{
"name": "@mintel/tsconfig",
"version": "1.6.0",
"version": "1.7.3",
"publishConfig": {
"access": "public",
"registry": "https://npm.infra.mintel.me"

View File

@@ -1,4 +1,3 @@
packages:
- 'packages/*'
- 'apps/*'
- '../klz-2026'

View File

@@ -4,9 +4,15 @@ import * as path from "path";
import { execSync } from "child_process";
/**
* Gets the current version tag from environment or git.
* Gets the current version tag from arguments, environment or git.
*/
function getVersionTag() {
// 0. Check arguments (passed from husky hook or manual run)
const argTag = process.argv.slice(2).find((arg) => arg.startsWith("v"));
if (argTag) {
return argTag;
}
// 1. Check CI environment variables
if (
process.env.GITHUB_REF_NAME &&
@@ -67,20 +73,50 @@ function updatePkg(pkgPath: string) {
console.log(`✅ Updated ${pkg.name} to ${version}`);
}
/**
* Updates the IMAGE_TAG in .env files.
*/
function updateEnv(envPath: string) {
if (!fs.existsSync(envPath)) return;
let content = fs.readFileSync(envPath, "utf-8");
if (content.includes("IMAGE_TAG=")) {
content = content.replace(/IMAGE_TAG=.*/g, `IMAGE_TAG=${tag}`);
} else {
// Proactively add it if missing
if (content.includes("# Project")) {
content = content.replace("# Project", `# Project\nIMAGE_TAG=${tag}`);
} else {
content = `IMAGE_TAG=${tag}\n${content}`;
}
}
fs.writeFileSync(envPath, content);
console.log(`✅ Updated IMAGE_TAG in ${envPath} to ${tag}`);
}
// Update root
rootPkg.version = version;
fs.writeFileSync("package.json", JSON.stringify(rootPkg, null, 2) + "\n");
// Update all packages
const packages = fs.readdirSync(packagesDir);
for (const p of packages) {
updatePkg(path.join(packagesDir, p, "package.json"));
if (fs.existsSync(packagesDir)) {
const packages = fs.readdirSync(packagesDir);
for (const p of packages) {
updatePkg(path.join(packagesDir, p, "package.json"));
}
}
// Update all apps
const apps = fs.readdirSync(appsDir);
for (const a of apps) {
updatePkg(path.join(appsDir, a, "package.json"));
if (fs.existsSync(appsDir)) {
const apps = fs.readdirSync(appsDir);
for (const a of apps) {
updatePkg(path.join(appsDir, a, "package.json"));
}
}
// Update .env files
updateEnv(".env");
updateEnv(".env.example");
console.log("✨ All versions synced!");