From d4d84ad0dbe1e168b587becd73e52ba358a596a6 Mon Sep 17 00:00:00 2001 From: badbl0cks <4161747+badbl0cks@users.noreply.github.com> Date: Thu, 31 Jul 2025 19:18:43 -0700 Subject: [PATCH] ci: implement 3-stage deployment pipeline with semantic-release --- .dockerignore | 37 ++++++- .gitignore | 1 - .releaserc.json | 45 +++++++- Dockerfile | 60 +++++++++-- LICENSE.md => LICENSE | 0 README.md | 133 ++++++++++++++++-------- deploy/docker-compose.yml | 18 +++- deploy/scripts/configure-haproxy.sh | 3 + deploy/scripts/deploy-blue-green.sh | 16 ++- deploy/scripts/generate-docker-tags.sh | 49 --------- deploy/scripts/parse-repository-name.sh | 40 ------- package-lock.json | 35 +++++-- package.json | 3 +- 13 files changed, 271 insertions(+), 169 deletions(-) rename LICENSE.md => LICENSE (100%) delete mode 100755 deploy/scripts/generate-docker-tags.sh delete mode 100755 deploy/scripts/parse-repository-name.sh diff --git a/.dockerignore b/.dockerignore index a056ef7..1bdd192 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,21 +1,50 @@ +# Dependencies and build artifacts node_modules .nuxt .output +dist +.cache +.parcel-cache + +# Git and version control .git +.gitignore + +# Environment files .env .env.local .env.*.local + +# Logs npm-debug.log* yarn-debug.log* yarn-error.log* +*.log + +# IDE and editor files .DS_Store .vscode .idea -*.log + +# Testing and coverage coverage .nyc_output -dist + +# Temporary files tmp temp -.cache -.parcel-cache \ No newline at end of file + +# Semantic-release artifacts (copied explicitly in final stage) +CHANGELOG.md + +# Development files +bun.lock + +# CI/CD files that don't need to be in the container +.github/ +.releaserc.json + +# Documentation that gets copied explicitly in final stage +README.md +LICENSE +CLAUDE.md \ No newline at end of file diff --git a/.gitignore b/.gitignore index 4814aed..6eeee75 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,6 @@ logs .idea public/headshot_pp.png .secrets -.claude # Local env files .env diff --git a/.releaserc.json b/.releaserc.json index 7bf2865..6a4fbf3 100644 --- a/.releaserc.json +++ b/.releaserc.json @@ -1,9 +1,44 @@ { - "branches": [ - "main" - ], + "branches": ["main"], + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { "type": "breaking", "section": "BREAKING CHANGES" }, + { "type": "feat", "section": "New Features" }, + { "type": "new", "section": "New Features" }, + { "type": "update", "section": "Dependencies" }, + { "type": "upgrade", "section": "Dependencies" }, + { "type": "deps", "section": "Dependencies" }, + { "type": "fix", "section": "Bug Fixes" }, + { "type": "build", "section": "Building and CI" }, + { "type": "ci", "section": "Building and CI" }, + { "type": "chore", "hidden": true }, + { "type": "docs", "hidden": true }, + { "type": "refactor", "hidden": true } + ] + }, "plugins": [ - "@semantic-release/commit-analyzer", + [ + "@semantic-release/commit-analyzer", + { + "releaseRules": [ + { "breaking": true, "release": "major" }, + { "revert": true, "release": "patch" }, + { "type": "breaking", "release": "major" }, + { "type": "feat", "release": "minor" }, + { "type": "update", "release": "minor" }, + { "type": "upgrade", "release": "minor" }, + { "type": "deps", "release": "minor" }, + { "type": "new", "release": "minor" }, + { "type": "fix", "release": "patch" }, + { "type": "build", "release": false }, + { "type": "ci", "release": false }, + { "type": "chore", "release": false }, + { "type": "docs", "release": false }, + { "type": "refactor", "release": false } + ] + } + ], "@semantic-release/release-notes-generator", "@semantic-release/changelog", [ @@ -16,7 +51,7 @@ [ "@semantic-release/git", { - "assets": ["CHANGELOG.md", "package.json", "package-lock.json", "bun.lock"], + "assets": ["CHANGELOG.md", "package.json", "package-lock.json"], "message": "chore: Release ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" } ] diff --git a/Dockerfile b/Dockerfile index dd033b1..573dec0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,19 +1,62 @@ -FROM node:24-slim +# Stage 1: Runtime dependencies +FROM node:24-slim AS deps +SHELL ["bash", "-exc"] + +WORKDIR /app + +# Install system dependencies +RUN apt-get update && apt-get install -y python3 make g++ curl net-tools && rm -rf /var/lib/apt/lists/* + +# Install dependencies +RUN --mount=type=bind,source=package-lock.json,target=package-lock.json --mount=type=bind,source=package.json,target=package.json npm ci --omit=dev && npm cache clean --force + +# Stage 2: Build dependencies - Includes dev dependencies for build +FROM node:24-slim AS build-deps +SHELL ["bash", "-exc"] + +WORKDIR /app + +ENV DEBIAN_FRONTEND=noninteractive + +# Install system dependencies +RUN apt-get update && apt-get install -y python3 make g++ curl net-tools && rm -rf /var/lib/apt/lists/* + +# Install all dependencies including dev dependencies for build +RUN --mount=type=bind,source=package-lock.json,target=package-lock.json --mount=type=bind,source=package.json,target=package.json npm ci && npm cache clean --force + +# Stage 3: Source and build - Cache invalidated when source code changes +FROM build-deps AS builder +SHELL ["bash", "-exc"] + +WORKDIR /app + +# Copy source code (excluding semantic-release artifacts) +COPY nuxt.config.ts tsconfig.json tailwind.config.js eslint.config.mjs ./ +COPY app/ ./app/ +COPY server/ ./server/ +COPY public/ ./public/ + +# Build the application (this is cached unless source code changes) +RUN npx nuxt build + +# Stage 4: Runtime assembly - Only invalidated by version/metadata changes +FROM deps AS runtime ARG VERSION=0.0.0 WORKDIR /app -RUN apt-get update && apt-get install -y python3 make g++ curl net-tools && rm -rf /var/lib/apt/lists/* +# Copy production node_modules from deps stage +COPY --from=deps /app/node_modules ./node_modules -COPY package.json package-lock.json* ./ +# Copy built application from builder stage +COPY --from=builder /app/.output ./.output -RUN npm ci - -COPY . . - -RUN npx nuxt build +# Copy package configs +# These change frequently but don't affect the expensive build steps above +COPY package.json package-lock.json ./ +# Set runtime environment ENV NUXT_HOST=0.0.0.0 ENV NUXT_PORT=3000 ENV NODE_ENV=production @@ -22,6 +65,7 @@ ENV APP_VERSION=${VERSION} ENV PUID=1000 ENV PGID=1000 +# Set up data directory and permissions RUN mkdir -p data && chown -R ${PUID}:${PGID} data && chown -R ${PUID}:${PGID} /app && chmod 755 /app data EXPOSE 3000 diff --git a/LICENSE.md b/LICENSE similarity index 100% rename from LICENSE.md rename to LICENSE diff --git a/README.md b/README.md index d31a3c0..26ae682 100644 --- a/README.md +++ b/README.md @@ -1,95 +1,142 @@ -# 🚀 Personal Portfolio Website +# 🚀 Portfolio Bonanza -My schnazzy portfolio turbocharged with Nuxt 4 and zero-downtime deployment wizardry! ✨ +A spicy little portfolio site with some absolutely ridiculous SMS shenanigans built on Nuxt 4! Looks like things are getting too spicy for the pepper! 🌶️ -## ⭐ What's Inside +## ✨ The Good Stuff -- 🌙 **Dark UI** with DaisyUI components -- 📱 **SMS Contact Form** with phone verification (because emails are so last millennium) -- 🎨 **Smooth animations** and typing effects -- 🐳 **Zero-downtime deployments** via Docker + HAProxy -- 🔐 **WireGuard tunnel** to home SMS gateway +- 🌙 **Night mode everything** - DaisyUI components that won't burn your eyeballs +- 📱 **SMS contact form** - Because I get wayyy too many emails already +- 🎭 **Snazzy animations** - ScrollReveal + Typed.js doing their thang +- 🐳 **Zero-downtime deploys** - Blue-green magic with Docker & HAProxy +- 🔧 **Overengineered infrastructure** - We like to do things the hard way over here -## 🚀 Quick Start +## 🏃‍♂️ Getting Started ```bash -# Install dependencies +# Grab the dependencies bun install -# Start development server +# Copy example env file and edit +cp .env.example .env && nano .env + +# Fire up the dev server bun run dev -# Build for production +# Build the contraption bun run build -# Generate static site +# Bake it bun run generate ``` -**Coffee Levels:** -☕ -☕☕ -☕☕☕ -☕☕☕☕ -🚨🚨🚨🚨🚨 +**Current vibe levels:** +😴 sleepy +🙂 caffeinated +🤓 productive +🔥 on fire +💀 send halp -## 📱 Contact System Flow +## 📞 Contact Form Wizardry -A bamboozling two-step form: collect message → verify phone → SMS me directly! -Rate limited to prevent spam-a-geddon. 🚫 +Two-step verification dance: drop your message → prove you're human with SMS → message gets yeeted to my phone via some questionable infrastructure choices. -## 🏗️ Architecture +Rate-limited because spam just sucksssss! 🛡️ + +## 🏗️ Infrastructure Tomfoolery + +Here's where things get ~completely~ unhinged: ``` -🌍 Internet → VPS → 🔐 WireGuard → 🏠 Android SMS Gateway +🌐 Your Browser → Some VPS → 🔐 WireGuard Tunnel +→ 🏠 Home Network → 🧟‍♂️ My Frankenstein Phone/SMS-Gateway +→ 📱 Someone's Legit Regular Phone ``` -Copy `.env.example` to `.env` for configuration. +### The SMS Gateway Setup + +I'm running the `android-sms-gateway` app on a completely deranged setup: +- **Hardware:** Pixel 1 with the battery surgically removed (no spicy pillows please) +- **Power:** Permanently plugged into the wall like some kind of cursed landline +- **Network:** Hardwired ethernet via USB-C adapter ("WhyFight" with WiFi?) +- **Purpose:** Sits there 24/7 just waiting to send OTPs and forward your messages to my actual phone + +The whole contraption lives on my home network and the VPS reaches it through a WireGuard tunnel because apparently I enjoy making simple things complicated just to save $2 a month! + +## 🌳 Git Workflow Madness + +This repo follows a three-branch strategy with automated promotions because manually managing branches is for chumps: + +- **`dev`** - Where the magic happens! All new features and fixes go here +- **`staging`** - Integration testing playground, auto-promoted from develop daily Monday-Friday at 13:00 UTC/05:00 AM PST +- **`main`** - Production branch, gets promoted from staging weekly on Mondays at 12:00 UTC/04:00 AM PST + +### The Repository Setup + +We're running a bit of a funky setup here: +- **Primary repo:** Self-hosted Forgejo instance (because it's more fun that way!) +- **Mirror:** GitHub (push-only mirror for CI/CD and visibility) +- **CI/CD:** GitHub Actions (triggered by the mirror's pushes or scheduled) + +So the workflow is: push to Forgejo origin → auto-mirrors to GitHub → GitHub Actions does the heavy lifting. + +### Branch Promotion Dance 💃 + +**Daily (develop → staging):** +- Checks if develop has new commits since last staging update +- Validates that the latest build actually passed +- Fast-forward merge to staging (keeps history clean) +- Supports `[skip ci]` in commit messages for any oopsies or boo-boos + +**Weekly (staging → main):** +- Runs semantic-release on staging for proper versioning +- Fast-forward merge to main for production release +- Some branch rebasing gymnastics to keep develop up-to-date +- Also supports `[skip ci]` ## 🚢 Deployment Shenanigans -Push to `staging` or `release` branches to trigger blue-green deployments! +Any (automated) pushes to `staging` or `main` branches to trigger blue-green staging and production deployments! Easy peasy lemon squeezy! ### Blue-Green Magic ✨ -1. **Build Phase:** Build new containers alongside old ones +1. **Build Phase:** Build new containers and validate 2. **Deploy Phase:** Health check the newbies -3. **Switch Phase:** HAProxy traffic switcheroo -4. **Cleanup Phase:** Cleanup old containers +3. **Switch Phase:** HAProxy config update and traffic switcheroo +4. **Cleanup Phase:** Nuke old containers from high orbit 5. **Moon Phases:** 🌑 🌒 🌓 🌔 🌝 🌖 🌗 🌘 🌚 ### GitHub Secrets Setup -Set these in your repo for deployment thingamajigs: -- `DEPLOY_KEY`, `DEPLOY_HOST` - SSH access stuff -- SMS gateway credentials and phone number -- `NUXT_SUPER_SECRET_SALT` - for cryptographic tomfoolery +Deployments generate the needed .env from GitHub secrets, so make sure to slap some secrets up first! ### WireGuard Setup -Copy `wireguard/wg0.conf.template` → `wg0.conf` and fill in your tunnel deets. +The stack is rocking gluetun, so just set up your WIREGUARD_ environment variables in Github secrets: ## 🔒 Security Fortress - 🔐 WireGuard tunnel encryption - 🛡️ Container firewalls and non-root execution - 🔢 TOTP phone verification + rate limiting -- 🔤 ASCII-only validation (emoji-proof!) +- 🔤 ASCII-only validation (No spammy weird characters please!) -## 🔧 Troubleshooting +## 🆘 When Things Go Wrong ```bash -# Check container health -docker-compose ps && docker logs portfolio +# Check if containers are actually alive +docker compose ps && docker compose logs portfolio -# Test SMS connectivity -docker exec portfolio curl -f http://192.168.0.XXX:9090 +# Poke the SMS gateway to see if it's responsive +docker compose exec portfolio curl -f http://your-sms-gateway-ip:9090/health + +# Check WireGuard tunnel status +docker compose exec portfolio wg show ``` -**Debug Panic Levels:** 😎 → 🤔 → 😅 → 😰 → 💀 → 🍕 +**Debugging stages of grief:** 😎 confident → 🤔 confused → 😅 nervous → 😰 panicking → 💀 accepting fate → 🍕 ordering pizza ## 📁 What's Where ``` ├── app/ # Nuxt 4 frontend -├── server/ # API routes + SMS gateway libs +├── server/ # API routes ├── deploy/ # Deployment scripts └── .github/ # CI/CD workflows ``` @@ -104,4 +151,4 @@ This project is licensed under **AGPL 3.0 only** - see the [LICENSE](LICENSE) fi --- -*Built with ❤️ and lots of ☕* +*Built with ❤️ and lots of ☕! (Sheesh, if you've read this far, just hire me, please!)* diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index c07a920..8a3eaae 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -1,6 +1,6 @@ services: portfolio: - image: badbl0cks/portfolio:${IMAGE_TAG:-stable} + image: ${IMAGE_NAME:-portfolio:latest} # image: ghcr.io/xe/x/httpdebug # entrypoint: ["/ko-app/httpdebug", "--bind", ":3000"] container_name: portfolio-${RELEASE_TYPE}-${DEPLOYMENT_COLOR} @@ -10,7 +10,7 @@ services: - portfolio-${RELEASE_TYPE} expose: - "3000" - env_file: + env_file: - .env volumes: - ./data:/app/data @@ -21,7 +21,16 @@ services: - "deployment.release_type=${RELEASE_TYPE}" user: "1000:1000" healthcheck: - test: ["CMD", "curl", "-f", "-s", "--max-time", "5", "http://localhost:3000/api/health"] + test: + [ + "CMD", + "curl", + "-f", + "-s", + "--max-time", + "5", + "http://localhost:3000/api/health", + ] interval: 30s timeout: 15s retries: 3 @@ -47,7 +56,8 @@ services: aliases: - wireguard-${RELEASE_TYPE} healthcheck: - test: ["CMD", "ping", "-c", "1", "-W", "3", "$$NUXT_ANDROID_SMS_GATEWAY_IP"] + test: + ["CMD", "ping", "-c", "1", "-W", "3", "$$NUXT_ANDROID_SMS_GATEWAY_IP"] interval: 30s timeout: 15s retries: 3 diff --git a/deploy/scripts/configure-haproxy.sh b/deploy/scripts/configure-haproxy.sh index 519a9fa..5e68fe2 100755 --- a/deploy/scripts/configure-haproxy.sh +++ b/deploy/scripts/configure-haproxy.sh @@ -10,6 +10,9 @@ else exit 1 fi +# Validate common required environment variables +require_var "DEPLOY_HOST" + readonly HAPROXY_BASE_DIR="/srv/haproxy" readonly HAPROXY_CONFIGS_DIR="${HAPROXY_BASE_DIR}/configs" readonly HAPROXY_COMPOSE_FILE="${HAPROXY_BASE_DIR}/docker-compose.yml" diff --git a/deploy/scripts/deploy-blue-green.sh b/deploy/scripts/deploy-blue-green.sh index 9bb2a16..5b99b30 100755 --- a/deploy/scripts/deploy-blue-green.sh +++ b/deploy/scripts/deploy-blue-green.sh @@ -9,14 +9,12 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${SCRIPT_DIR}/common-lib.sh" # Validate required environment variables -require_var "DOCKER_HOST" -require_var "REPO_PROJECT_PATH" -require_var "REPO_NAME_ONLY" -require_var "REPO" require_var "IMAGE_TAR" require_var "PROD" require_var "DOMAIN" require_var "WIREGUARD_ENDPOINT_HOST" +require_var "REPO_PROJECT_PATH" +require_var "DEPLOY_HOST" validate_deployment_env @@ -76,10 +74,18 @@ echo "DEPLOYMENT_COLOR=\"${NEW_COLOR}\"" >> .env echo "RELEASE_TYPE=\"${RELEASE_TYPE}\"" >> .env echo "WIREGUARD_ENDPOINT_IP=\"${WIREGUARD_ENDPOINT_IP}\"" >> .env +# Set computed image name based on release type +if [ "$RELEASE_TYPE" = "staging" ]; then + IMAGE_NAME="portfolio-dev:${IMAGE_TAG}" +else + IMAGE_NAME="portfolio:${IMAGE_TAG}" +fi +echo "IMAGE_NAME=\"${IMAGE_NAME}\"" >> .env + echo "📋 Copying deployment files..." scp deploy/docker-compose.yml deploy/haproxy.cfg .env deploy:"${NEW_RELEASE_PATH}/" -echo "🐳 Loading Docker image..." +echo "🐳 Loading Docker image (${IMAGE_TAR})..." docker load -i "${IMAGE_TAR}" PROJECT_NAME=$(get_project_name "$NEW_COLOR") diff --git a/deploy/scripts/generate-docker-tags.sh b/deploy/scripts/generate-docker-tags.sh deleted file mode 100755 index 30cfb4d..0000000 --- a/deploy/scripts/generate-docker-tags.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash -set -euo pipefail - -# Generate Docker tags based on git ref and environment -# Usage: ./generate-docker-tags.sh IMAGE_BASE GIT_SHA GIT_REF PROD - -if [ $# -ne 4 ]; then - echo "Error: Invalid number of arguments" > /dev/stderr - echo "Usage: $0 IMAGE_BASE GIT_SHA GIT_REF PROD" > /dev/stderr - exit 1 -fi - -IMAGE_BASE="$1" -GIT_SHA="$2" -GIT_REF="$3" -PROD="$4" - -# Validate inputs -if [ -z "$IMAGE_BASE" ] || [ -z "$GIT_SHA" ]; then - echo "Error: IMAGE_BASE and GIT_SHA cannot be empty" > /dev/stderr - exit 1 -fi - -# Always include SHA tags -echo "${IMAGE_BASE}:sha-${GIT_SHA:0:7}" -echo "${IMAGE_BASE}:sha-${GIT_SHA}" - -# Handle version tags -if [[ "$GIT_REF" =~ ^refs/tags/v([0-9]+)\.([0-9]+)\.([0-9]+)(-.*)?$ ]]; then - MAJOR="${BASH_REMATCH[1]}" - MINOR="${BASH_REMATCH[2]}" - PATCH="${BASH_REMATCH[3]}" - PRERELEASE="${BASH_REMATCH[4]}" - - if [[ -z "$PRERELEASE" ]] && [[ "$PROD" == "true" ]]; then - echo "${IMAGE_BASE}:latest" - echo "${IMAGE_BASE}:stable" - [[ "$MAJOR" -gt 0 ]] && echo "${IMAGE_BASE}:v${MAJOR}" - echo "${IMAGE_BASE}:v${MAJOR}.${MINOR}" - echo "${IMAGE_BASE}:v${MAJOR}.${MINOR}.${PATCH}" - else - echo "${IMAGE_BASE}:latest-staging" - echo "${IMAGE_BASE}:staging" - echo "${IMAGE_BASE}:v${MAJOR}.${MINOR}.${PATCH}-prerelease" - fi -elif [[ "$PROD" == "false" ]]; then - echo "${IMAGE_BASE}:latest-staging" - echo "${IMAGE_BASE}:staging" -fi diff --git a/deploy/scripts/parse-repository-name.sh b/deploy/scripts/parse-repository-name.sh deleted file mode 100755 index 6093426..0000000 --- a/deploy/scripts/parse-repository-name.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash -set -euo pipefail - -# Parse repository name and generate project paths -# Usage: ./parse-repository-name.sh GITHUB_REPOSITORY - -if [ $# -eq 0 ]; then - echo "Error: No repository name provided" > /dev/stderr - echo "Usage: $0 GITHUB_REPOSITORY" > /dev/stderr - exit 1 -fi - -GITHUB_REPOSITORY="$1" - -echo "GITHUB_REPOSITORY: $GITHUB_REPOSITORY" > /dev/stderr - -if [[ "$GITHUB_REPOSITORY" == *".git" ]]; then - if [[ "$GITHUB_REPOSITORY" == "https://"* ]]; then - echo "GITHUB_REPOSITORY ends in .git and is an HTTPS URI" > /dev/stderr - REPO=$(echo "$GITHUB_REPOSITORY" | sed 's/\.git$//' | cut -d'/' -f4-5 | sed 's/[^a-zA-Z0-9\/-]/-/g') - elif [[ "$GITHUB_REPOSITORY" == "git@"* ]]; then - echo "GITHUB_REPOSITORY ends in .git and is an SSH URI" > /dev/stderr - REPO=$(echo "$GITHUB_REPOSITORY" | sed 's/\.git$//' | cut -d':' -f2 | sed 's/[^a-zA-Z0-9\/-]/-/g') - else - echo "GITHUB_REPOSITORY ends in .git and is not a URI" > /dev/stderr - REPO=$(echo "$GITHUB_REPOSITORY" | sed 's/\.git$//' | sed 's/[^a-zA-Z0-9\/-]/-/g') - fi -else - echo "GITHUB_REPOSITORY is not a URI" > /dev/stderr - REPO=$(echo "$GITHUB_REPOSITORY" | sed 's/[^a-zA-Z0-9\/-]/-/g') -fi - -REPO_NAME_ONLY=$(echo "$REPO" | cut -d'/' -f2) -# Default path - will be modified by deployment script based on environment -REPO_PROJECT_PATH="/srv/${REPO_NAME_ONLY}" - -# Output in format that can be sourced - using printf %q for proper escaping -printf "export REPO=%q\n" "$REPO" -printf "export REPO_NAME_ONLY=%q\n" "$REPO_NAME_ONLY" -printf "export REPO_PROJECT_PATH=%q\n" "$REPO_PROJECT_PATH" \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 3309f93..9670a26 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "portfolio", - "version": "0.0.0-development", + "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "portfolio", - "version": "0.0.0-development", + "version": "0.0.1", "hasInstallScript": true, "dependencies": { "@nuxt/fonts": "0.11.4", @@ -16,6 +16,7 @@ "@nuxt/ui": "3.2.0", "@unhead/vue": "^2.0.12", "android-sms-gateway": "^3.0.0", + "conventional-changelog-conventionalcommits": "^9.1.0", "daisyui": "^5.0.46", "husky": "^9.1.7", "nuxt": "^4.0.1", @@ -784,7 +785,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.3", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz", + "integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==", "devOptional": true, "license": "Apache-2.0", "dependencies": { @@ -5910,7 +5913,6 @@ }, "node_modules/array-ify": { "version": "1.0.0", - "dev": true, "license": "MIT" }, "node_modules/ast-kit": { @@ -6848,7 +6850,6 @@ }, "node_modules/compare-func": { "version": "2.0.0", - "dev": true, "license": "MIT", "dependencies": { "array-ify": "^1.0.0", @@ -6857,7 +6858,6 @@ }, "node_modules/compare-func/node_modules/dot-prop": { "version": "5.3.0", - "dev": true, "license": "MIT", "dependencies": { "is-obj": "^2.0.0" @@ -6959,6 +6959,18 @@ "node": ">=18" } }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-9.1.0.tgz", + "integrity": "sha512-MnbEysR8wWa8dAEvbj5xcBgJKQlX/m0lhS8DsyAAWDHdfs2faDJxTgzRYlRYpXSe7UiKrIIlB4TrBKU9q9DgkA==", + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/conventional-changelog-writer": { "version": "8.2.0", "dev": true, @@ -9988,7 +10000,9 @@ } }, "node_modules/ipx": { - "version": "2.1.0", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ipx/-/ipx-2.1.1.tgz", + "integrity": "sha512-XuM9FEGOT+/45mfAWZ5ykwkZ/oE7vWpd1iWjRffMWlwAYIRzb/xD6wZhQ4BzmPMX6Ov5dqK0wUyD0OEN9oWT6g==", "license": "MIT", "optional": true, "dependencies": { @@ -10184,7 +10198,6 @@ }, "node_modules/is-obj": { "version": "2.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -16673,6 +16686,8 @@ }, "node_modules/semantic-release": { "version": "24.2.7", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.2.7.tgz", + "integrity": "sha512-g7RssbTAbir1k/S7uSwSVZFfFXwpomUB9Oas0+xi9KStSCmeDXcA7rNhiskjLqvUe/Evhx8fVCT16OSa34eM5g==", "dev": true, "license": "MIT", "dependencies": { @@ -17996,7 +18011,9 @@ } }, "node_modules/tmp": { - "version": "0.2.3", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.4.tgz", + "integrity": "sha512-UdiSoX6ypifLmrfQ/XfiawN6hkjSBpCjhKxxZcWlUUmoXLaCKQU0bx4HF/tdDK2uzRuchf1txGvrWBzYREssoQ==", "license": "MIT", "engines": { "node": ">=14.14" diff --git a/package.json b/package.json index 7ebe914..ad4f11c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "portfolio", - "version": "0.0.0-development", + "version": "0.0.1", "private": true, "type": "module", "scripts": { @@ -31,6 +31,7 @@ "@nuxt/ui": "3.2.0", "@unhead/vue": "^2.0.12", "android-sms-gateway": "^3.0.0", + "conventional-changelog-conventionalcommits": "^9.1.0", "daisyui": "^5.0.46", "husky": "^9.1.7", "nuxt": "^4.0.1",