From d3fec4b85a5a08a1122f9d8a2b7267c77c3ce037 Mon Sep 17 00:00:00 2001 From: sHa Date: Sat, 27 Sep 2025 02:27:53 +0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20MAJOR:=20Full=20migration=20to?= =?UTF-8?q?=20Just=20modules=20with=20modern=20features?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING CHANGES: - Complete restructure to Just module architecture (requires Just 1.31.0+) - Command syntax changed: 'just postgres-sql' → 'just postgres sql' - Import syntax changed: import → mod declarations NEW FEATURES: ✨ Module-based architecture with optional modules ✨ Built-in Just colors ({{RED}}, {{GREEN}}, etc.) replace custom variables ✨ Enhanced [confirm] attributes for all destructive operations ✨ Organized [group('name')] attributes for better UX ✨ Modern justfile with comprehensive help system ✨ Updated documentation with migration guide MODULES: 📦 postgres/ - PostgreSQL operations (sql, check, create-database, etc.) 📦 mysql/ - MySQL operations (sql, check, create-user, etc.) 📦 volumes/ - Volume management (clean-all, remove, list) 📦 container/ - Container operations (start, stop, logs, shell, exec) 📦 registry/ - Registry auth (login, logout, check) 📦 images/ - Image operations (build, push, pull, tag, clean) USAGE: just postgres sql "SELECT version();" just volumes clean-all just images build myapp This is Just Commons v2.0 - a complete modernization using all of Just's latest features. --- README.md | 388 +++++++++++++++++++++------ container.just => container/mod.just | 36 +-- core.just | 26 +- images.just | 375 -------------------------- images/mod.just | 294 ++++++++++++++++++++ justfile | 106 ++++++++ mysql.just => mysql/mod.just | 105 ++++---- postgres.just => postgres/mod.just | 81 +++--- registry.just | 175 ------------ registry/mod.just | 65 +++++ volumes.just => volumes/mod.just | 52 ++-- 11 files changed, 928 insertions(+), 775 deletions(-) rename container.just => container/mod.just (75%) delete mode 100644 images.just create mode 100644 images/mod.just create mode 100644 justfile rename mysql.just => mysql/mod.just (73%) rename postgres.just => postgres/mod.just (72%) delete mode 100644 registry.just create mode 100644 registry/mod.just rename volumes.just => volumes/mod.just (68%) diff --git a/README.md b/README.md index 08cfb16..d82c29c 100644 --- a/README.md +++ b/README.md @@ -1,89 +1,24 @@ -# Just Commons +# Just Commons - Universal Command Library -Universal Just command recipes for container management across projects. +**Version 2.0 - Modern Module Architecture** -## Overview +A collection of universal Just command modules for container management, database operations, and development workflows. Built with Just's modern module system and designed for maximum reusability. -This repository contains reusable Just recipes for: -- **Container operations**: start, stop, restart, logs, shell, exec, status -- **Registry authentication**: login, logout, status checks for GitHub Container Registry -- **Image operations**: build, push, pull, tag, test, info, clean -- **Database operations**: PostgreSQL and MySQL database management +## 🚀 Features -## Usage +- **🎯 Module-Based Architecture**: Clean separation using Just's native module system +- **🎨 Modern Just Features**: Built-in colors, groups, and confirm attributes +- **📦 Optional Modules**: Include only what you need +- **🐳 Universal Container Support**: Works with Docker and Podman +- **🗄️ Database Operations**: PostgreSQL and MySQL support +- **🔒 Built-in Safety**: Confirmation prompts for destructive operations +- **🏗️ Zero Dependencies**: Pure Just recipes with automatic runtime detection -Add as a Git submodule to your project: - -```bash -git submodule add git@github.com:shadoll/just-commons.git -``` - -Import in your `justfile`: - -```bash -# Import universal commands -import 'just-commons/core.just' # Core utilities -import 'just-commons/container.just' # Container operations -import 'just-commons/registry.just' # Registry authentication -import 'just-commons/images.just' # Image operations - -# Import database and volume commands (optional) -import 'just-commons/postgres.just' # PostgreSQL operations -import 'just-commons/mysql.just' # MySQL operations -import 'just-commons/volumes.just' # Volume management -``` - -## Files - -### Core Files -- `core.just` - Core utilities (_detect_runtime, _detect_compose, env-check) -- `container.just` - Universal container operations (start, stop, logs, shell, exec, status) -- `registry.just` - GitHub Container Registry authentication (registry-login, registry-logout, registry-check) -- `images.just` - Universal image operations (image-build, image-push, image-pull, image-tag, etc.) - -### Database Files (Optional) -- `postgres.just` - PostgreSQL operations (postgres-sql, postgres-check, postgres-list-databases, etc.) -- `mysql.just` - MySQL operations (mysql-sql, mysql-check, mysql-list-databases, etc.) - -### Volume Management (Optional) -- `volumes.just` - Volume operations (volumes-clean-all, volumes-remove, volumes-list, etc.) - -### Command Structure -- **Container commands**: No prefix (start, stop, logs, shell, exec, status, restart) -- **All other commands**: Prefixed by file type (image-*, registry-*, postgres-*, mysql-*) - -### Usage Examples - -```bash -# Container operations (no prefix) -just start postgres -just logs postgres -just shell postgres - -# Image operations (image- prefix) -just image-build postgres -just image-push postgres v1.0.0 - -# Registry operations (registry- prefix) -just registry-login -just registry-check - -# Database operations (database- prefix) -just postgres-sql "SELECT version();" -just postgres-check -just mysql-sql "SELECT VERSION();" - -# Volume operations (volumes- prefix) -just volumes-list "myproject_*" -just volumes-clean-all -just volumes-remove "old_volume" -``` - -## Requirements +## 📋 Requirements ### Just Command Runner -This library requires **Just 1.14.0 or later** to support the `group` attribute for organized command display. +This library requires **Just 1.31.0 or later** for module support and modern features. #### Installation on Ubuntu 24.04 LTS @@ -107,6 +42,303 @@ chmod +x /usr/local/bin/just just --version ``` +#### Other Platforms +- **macOS**: `brew install just` +- **Windows**: `choco install just` or `scoop install just` +- **Other Linux**: See [official installation guide](https://github.com/casey/just#installation) + ### Other Requirements - Docker or Podman - Git + +## 🏗️ Module Architecture + +``` +just-commons/ +├── README.md # This documentation +├── justfile # Main file with module declarations and help +├── core.just # Shared utilities (imported) +├── postgres/ +│ └── mod.just # PostgreSQL module +├── mysql/ +│ └── mod.just # MySQL module +├── volumes/ +│ └── mod.just # Volume management module +├── container/ +│ └── mod.just # Container operations module +├── registry/ +│ └── mod.just # Registry authentication module +└── images/ + └── mod.just # Image operations module +``` + +## 🔧 Usage + +### Add as Git Submodule + +```bash +git submodule add git@github.com:shadoll/just-commons.git just-commons +cd just-commons +git checkout main +``` + +### Import in Your Justfile + +```just +# Import core utilities (required) +import 'just-commons/core.just' + +# Declare optional modules (use only what you need) +mod? postgres 'just-commons/postgres' +mod? mysql 'just-commons/mysql' +mod? volumes 'just-commons/volumes' +mod? container 'just-commons/container' +mod? registry 'just-commons/registry' +mod? images 'just-commons/images' +``` + +### Example Project Justfile + +```just +# My Project Justfile +import 'just-commons/core.just' + +# Only include modules I need +mod? container 'just-commons/container' +mod? postgres 'just-commons/postgres' +mod? volumes 'just-commons/volumes' + +# Project-specific commands +[group('project')] +setup: + just container start + just postgres sql "CREATE DATABASE myapp;" + +[group('project')] +teardown: + just volumes clean-all +``` + +## 📚 Available Modules + +### 🐳 Container Module (`container`) + +**Universal container operations with optional compose file support** + +```bash +just container start [service] [compose-file] # Start services +just container stop [service] [compose-file] # Stop services +just container restart [service] [compose-file] # Restart services +just container status [service] [compose-file] # Show service status +just container logs [service] [compose-file] # View service logs +just container shell [compose-file] # Open shell in container +just container exec [compose-file] # Execute command +``` + +### 🗄️ Database Modules + +#### PostgreSQL Module (`postgres`) + +```bash +just postgres sql [service] [compose-file] # Execute SQL query +just postgres check [service] [compose-file] # Check connection +just postgres list-databases [service] [compose-file] # List databases +just postgres list-users [service] [compose-file] # List users +just postgres create-database [service] # Create database +just postgres drop-database [service] # Drop database (with confirmation) +just postgres shell [service] [compose-file] # Interactive shell +just postgres restore [service] [compose-file] # Restore from backup (with confirmation) +``` + +#### MySQL Module (`mysql`) + +```bash +just mysql sql [service] [compose-file] # Execute SQL query +just mysql check [service] [compose-file] # Check connection +just mysql list-databases [service] [compose-file] # List databases +just mysql list-users [service] [compose-file] # List users +just mysql create-database [service] # Create database +just mysql drop-database [service] # Drop database (with confirmation) +just mysql create-user [service] # Create user +just mysql grant-privileges [service] # Grant privileges +just mysql shell [service] [compose-file] # Interactive shell +just mysql restore [service] # Restore from backup (with confirmation) +``` + +### 💾 Volume Module (`volumes`) + +**Safe volume management with built-in confirmations** + +```bash +just volumes clean-all [compose-file] # Remove all compose volumes (with confirmation) +just volumes remove # Remove specific volume (with confirmation) +just volumes remove-pattern # Remove volumes matching pattern (with confirmation) +just volumes list [pattern] # List volumes (optionally filtered) +``` + +### 🐋 Images Module (`images`) + +**Universal image operations with automatic registry detection** + +```bash +just images build [tag] # Build project image +just images push [tag] # Push image to registry +just images pull [tag] # Pull image from registry +just images tag # Tag existing image +just images info [tag] # Show image information +just images clean # Remove project images (with confirmation) +just images build-all # Build all projects with Containerfiles +``` + +### 🔐 Registry Module (`registry`) + +**Container registry authentication management** + +```bash +just registry login # Login to container registry +just registry logout # Logout from registry +just registry check # Check authentication status +``` + +### 🔧 Core Utilities + +**Shared functions and environment checking** + +```bash +just env-check # Check container runtime availability +just _detect_runtime # Internal: Detect Docker/Podman +just _detect_compose # Internal: Detect compose command +``` + +## 🎨 Modern Just Features + +### Built-in Colors +Uses Just's native color constants instead of custom ANSI codes: +- `{{RED}}`, `{{GREEN}}`, `{{BLUE}}`, `{{YELLOW}}` +- `{{BOLD}}`, `{{NORMAL}}` + +### Command Groups +All commands are organized with `[group('name')]` attributes: +- `container` - Container operations +- `database` - Database operations +- `volumes` - Volume management +- `images` - Image operations +- `registry` - Registry operations +- `environment` - Environment checking + +### Safety Confirmations +Destructive operations use `[confirm]` attribute: +- Volume removal operations +- Database dropping +- Image cleaning +- Backup restoration + +## 🌍 Environment Configuration + +### Required for Registry Operations +```bash +# .env file +GITHUB_USERNAME=your-username +GITHUB_TOKEN=ghp_your-token +REGISTRY=ghcr.io +``` + +### Optional Overrides +```bash +# Auto-detected, but can be explicitly set +CONTAINER_RUNTIME=docker # or 'podman' +COMPOSE_CMD="docker compose" # or 'podman-compose' +``` + +## 📖 Usage Examples + +### Development Workflow +```bash +# Environment setup +just env-check # Verify container runtime +just registry login # Authenticate with registry + +# Container management +just container start postgres # Start PostgreSQL service +just container logs postgres # View logs +just postgres check # Test database connection + +# Development operations +just postgres sql "CREATE DATABASE myapp;" # Create development database +just images build myapp # Build application image +just images push myapp dev # Push development version +``` + +### Production Deployment +```bash +# Pull latest images +just images pull myapp latest +just images pull postgres 15 + +# Database operations +just postgres restore latest-backup.sql # Restore from backup (with confirmation) +just postgres sql "ANALYZE;" # Optimize database + +# Volume management +just volumes list "production_*" # List production volumes +just volumes clean-all compose.prod.yml # Clean up old volumes (with confirmation) +``` + +### Multi-Database Setup +```bash +# PostgreSQL setup +just postgres create-database main_db +just postgres sql "CREATE USER app_user WITH PASSWORD 'secret';" postgres + +# MySQL setup +just mysql create-database cache_db +just mysql create-user cache_user secret123 mysql +just mysql grant-privileges cache_db cache_user mysql +``` + +## 🆕 Migration from Version 1.x + +**Breaking Changes in Version 2.0:** + +### Command Structure +- **Old**: `just postgres-sql "query"` +- **New**: `just postgres sql "query"` + +### Module Declaration +- **Old**: `import 'just-commons/postgres.just'` +- **New**: `mod postgres 'just-commons/postgres'` + +### Color Variables +- **Old**: Custom `${GREEN}`, `${RED}` variables +- **New**: Built-in `{{GREEN}}`, `{{RED}}` constants + +### Migration Steps +1. Update to Just 1.31.0+ +2. Replace `import` statements with `mod` declarations +3. Update command calls to use module syntax +4. Remove custom color variable definitions + +## 🤝 Contributing + +1. Fork the repository +2. Create feature branch: `git checkout -b feature/new-module` +3. Follow existing module patterns +4. Use modern Just features (groups, confirm, built-in colors) +5. Test across different environments +6. Update documentation +7. Submit pull request + +## 📝 License + +MIT License - see LICENSE file for details. + +## 🔗 Links + +- [Just Command Runner](https://just.systems/) +- [Just Documentation](https://just.systems/man/en/) +- [Docker](https://docs.docker.com/) +- [Podman](https://podman.io/) + +--- + +**Just Commons v2.0** - Modern, modular, and maintainable command automation for container-based projects. \ No newline at end of file diff --git a/container.just b/container/mod.just similarity index 75% rename from container.just rename to container/mod.just index 6e56748..ac3d70b 100644 --- a/container.just +++ b/container/mod.just @@ -17,13 +17,13 @@ start service="" compose-file="": fi if [ -n "$service" ]; then - echo -e "{{BLUE}}Starting service: $service{{NC}}" + echo -e "{{BLUE}}Starting service: $service{{NORMAL}}" $compose_cmd $file_arg up -d "$service" - echo -e "{{GREEN}}✓ Service $service started{{NC}}" + echo -e "{{GREEN}}✓ Service $service started{{NORMAL}}" else - echo -e "{{BLUE}}Starting all services...{{NC}}" + echo -e "{{BLUE}}Starting all services...{{NORMAL}}" $compose_cmd $file_arg up -d - echo -e "{{GREEN}}✓ All services started{{NC}}" + echo -e "{{GREEN}}✓ All services started{{NORMAL}}" fi # Stop service (or all services if no service specified) @@ -43,13 +43,13 @@ stop service="" compose-file="": fi if [ -n "$service" ]; then - echo -e "{{BLUE}}Stopping service: $service{{NC}}" + echo -e "{{BLUE}}Stopping service: $service{{NORMAL}}" $compose_cmd $file_arg stop "$service" - echo -e "{{GREEN}}✓ Service $service stopped{{NC}}" + echo -e "{{GREEN}}✓ Service $service stopped{{NORMAL}}" else - echo -e "{{BLUE}}Stopping all services...{{NC}}" + echo -e "{{BLUE}}Stopping all services...{{NORMAL}}" $compose_cmd $file_arg down - echo -e "{{GREEN}}✓ All services stopped{{NC}}" + echo -e "{{GREEN}}✓ All services stopped{{NORMAL}}" fi # Restart service (or all services if no service specified) @@ -69,12 +69,12 @@ restart service="" compose-file="": fi if [ -n "$service" ]; then - echo -e "{{BLUE}}Restarting service: $service{{NC}}" + echo -e "{{BLUE}}Restarting service: $service{{NORMAL}}" $compose_cmd $file_arg restart "$service" - echo -e "{{GREEN}}✓ Service $service restarted{{NC}}" + echo -e "{{GREEN}}✓ Service $service restarted{{NORMAL}}" else - just stop "$service" "$compose_file" - just start "$service" "$compose_file" + just container stop "$service" "$compose_file" + just container start "$service" "$compose_file" fi # Show service status (specific service or all) @@ -94,10 +94,10 @@ status service="" compose-file="": fi if [ -n "$service" ]; then - echo -e "{{BLUE}}Status for: $service{{NC}}" + echo -e "{{BLUE}}Status for: $service{{NORMAL}}" $compose_cmd $file_arg ps "$service" else - echo -e "{{BLUE}}Service Status:{{NC}}" + echo -e "{{BLUE}}Service Status:{{NORMAL}}" $compose_cmd $file_arg ps fi @@ -118,10 +118,10 @@ logs service="" compose-file="": fi if [ -n "$service" ]; then - echo -e "{{BLUE}}Showing logs for: $service{{NC}}" + echo -e "{{BLUE}}Showing logs for: $service{{NORMAL}}" $compose_cmd $file_arg logs -f "$service" else - echo -e "{{BLUE}}Showing logs for all services{{NC}}" + echo -e "{{BLUE}}Showing logs for all services{{NORMAL}}" $compose_cmd $file_arg logs -f fi @@ -141,7 +141,7 @@ shell service compose-file="": file_arg="-f $compose_file" fi - echo -e "{{BLUE}}Opening shell in: $service{{NC}}" + echo -e "{{BLUE}}Opening shell in: $service{{NORMAL}}" $compose_cmd $file_arg exec "$service" /bin/bash # Execute command in specific service container @@ -161,5 +161,5 @@ exec service cmd compose-file="": file_arg="-f $compose_file" fi - echo -e "{{BLUE}}Executing in $service: $cmd{{NC}}" + echo -e "{{BLUE}}Executing in $service: $cmd{{NORMAL}}" $compose_cmd $file_arg exec "$service" bash -c "$cmd" \ No newline at end of file diff --git a/core.just b/core.just index e744230..b0b7864 100644 --- a/core.just +++ b/core.just @@ -45,12 +45,6 @@ env-check: #!/usr/bin/env bash set -euo pipefail - # Colors - RED='\033[0;31m' - GREEN='\033[0;32m' - YELLOW='\033[1;33m' - BLUE='\033[0;34m' - NC='\033[0m' echo "================================================" echo " Container Environment Detection" @@ -60,23 +54,23 @@ env-check: # Check Docker if command -v docker >/dev/null 2>&1; then if docker info >/dev/null 2>&1; then - echo -e "${GREEN}✓ Docker Engine detected and running${NC}" + echo -e "{{GREEN}}✓ Docker Engine detected and running{{NORMAL}}" docker_available=true else - echo -e "${YELLOW}⚠ Docker is installed but daemon is not running${NC}" + echo -e "{{YELLOW}}⚠ Docker is installed but daemon is not running{{NORMAL}}" docker_available=false fi else - echo -e "${RED}✗ Docker not found${NC}" + echo -e "{{RED}}✗ Docker not found{{NORMAL}}" docker_available=false fi # Check Podman if command -v podman >/dev/null 2>&1; then - echo -e "${GREEN}✓ Podman detected${NC}" + echo -e "{{GREEN}}✓ Podman detected{{NORMAL}}" podman_available=true else - echo -e "${RED}✗ Podman not found${NC}" + echo -e "{{RED}}✗ Podman not found{{NORMAL}}" podman_available=false fi @@ -86,14 +80,14 @@ env-check: echo "================================================" if [ "$docker_available" = true ] || [ "$podman_available" = true ]; then - echo -e "${GREEN}🎉 Container runtime available!${NC}" + echo -e "{{GREEN}}🎉 Container runtime available!{{NORMAL}}" echo "" echo "You can use these universal commands:" - echo " just build # Build any project image" - echo " just start # Start any service" - echo " just registry-login # Login to registry" + echo " just images build # Build any project image" + echo " just container start # Start any service" + echo " just registry login # Login to registry" else - echo -e "${RED}❌ No container runtime available${NC}" + echo -e "{{RED}}❌ No container runtime available{{NORMAL}}" echo "" echo "Please install Docker or Podman:" echo " • Docker: https://docs.docker.com/get-docker/" diff --git a/images.just b/images.just deleted file mode 100644 index ef49a6e..0000000 --- a/images.just +++ /dev/null @@ -1,375 +0,0 @@ -# Universal image operations - works for any project - -# Build any project's container image -[group('images')] -image-build project *args="": - #!/usr/bin/env bash - set -euo pipefail - - # Colors - GREEN='\033[0;32m' - BLUE='\033[0;34m' - YELLOW='\033[1;33m' - RED='\033[0;31m' - NC='\033[0m' - - project="{{project}}" - args="{{args}}" - - # Use default tag if not specified - tag="commit-$(git rev-parse --short HEAD)" - - # Validate project directory exists - if [ ! -d "$project" ]; then - echo -e "${RED}Error: Project directory '$project' not found${NC}" >&2 - exit 1 - fi - - # Look for Containerfile or Dockerfile - containerfile="" - if [ -f "$project/Containerfile" ]; then - containerfile="Containerfile" - elif [ -f "$project/Dockerfile" ]; then - containerfile="Dockerfile" - else - echo -e "${RED}Error: No Containerfile or Dockerfile found in '$project'${NC}" >&2 - exit 1 - fi - - # Detect runtime - runtime=$(just _detect_runtime) - - # Build image - echo -e "${BLUE}Building $project image with tag: $tag${NC}" - cd "$project" - - # Create full image name with registry - full_image_name="{{REGISTRY}}/${GITHUB_USERNAME:-local}/$project:$tag" - - echo -e "${YELLOW}Building: $full_image_name${NC}" - $runtime build $args -t "$full_image_name" -f "$containerfile" . - - # Also tag as local for development - $runtime tag "$full_image_name" "$project:$tag" - $runtime tag "$full_image_name" "$project:latest" - - echo -e "${GREEN}✓ Image $project:$tag built successfully${NC}" - echo -e "${GREEN}✓ Tagged as: $full_image_name${NC}" - echo -e "${GREEN}✓ Local tags: $project:$tag, $project:latest${NC}" - -# Push any project's image to registry -[group('images')] -image-push project tag=DEFAULT_TAG: - #!/usr/bin/env bash - set -euo pipefail - - # Colors - GREEN='\033[0;32m' - BLUE='\033[0;34m' - RED='\033[0;31m' - NC='\033[0m' - - project="{{project}}" - tag="{{tag}}" - - # Load environment variables from .env file - if [ -f ".env" ]; then - source .env - else - echo -e "${RED}Error: .env file not found${NC}" >&2 - echo "Create .env file with your GitHub credentials" >&2 - exit 1 - fi - - # Check loaded variables - if [ -z "${GITHUB_USERNAME:-}" ]; then - echo -e "${RED}Error: GITHUB_USERNAME not set in .env file${NC}" >&2 - exit 1 - fi - - if [ -z "${GITHUB_TOKEN:-}" ]; then - echo -e "${RED}Error: GITHUB_TOKEN not set in .env file${NC}" >&2 - echo "Add your token to .env file: GITHUB_TOKEN=your-token" >&2 - exit 1 - fi - - # Detect runtime - runtime=$(just _detect_runtime) - - # Login first - echo "$GITHUB_TOKEN" | $runtime login {{REGISTRY}} -u "$GITHUB_USERNAME" --password-stdin - - # Handle special case: pushing as "latest" means push both commit tag and latest - if [ "$tag" = "latest" ]; then - # Get current commit tag - if git rev-parse --git-dir >/dev/null 2>&1; then - commit_tag="commit-$(git rev-parse --short HEAD)" - else - commit_tag="build-$(date '+%Y%m%d-%H%M%S')" - fi - - commit_image_name="{{REGISTRY}}/$GITHUB_USERNAME/$project:$commit_tag" - latest_image_name="{{REGISTRY}}/$GITHUB_USERNAME/$project:latest" - - echo -e "${BLUE}Pushing $project as latest (both $commit_tag and latest tags)...${NC}" - - # Tag the local image with both commit and latest registry tags - $runtime tag "$project:latest" "$commit_image_name" - $runtime tag "$project:latest" "$latest_image_name" - - # Push both tags - $runtime push "$commit_image_name" - $runtime push "$latest_image_name" - - echo -e "${GREEN}✓ Pushed as: $commit_image_name${NC}" - echo -e "${GREEN}✓ Pushed as: $latest_image_name${NC}" - else - # Normal push: just push the specific tag - full_image_name="{{REGISTRY}}/$GITHUB_USERNAME/$project:$tag" - - echo -e "${BLUE}Pushing $project:$tag to registry...${NC}" - $runtime push "$full_image_name" - echo -e "${GREEN}✓ Image pushed successfully: $full_image_name${NC}" - fi - -# Pull any project's image from registry -[group('images')] -image-pull project tag=DEFAULT_TAG: - #!/usr/bin/env bash - set -euo pipefail - - # Colors - GREEN='\033[0;32m' - BLUE='\033[0;34m' - RED='\033[0;31m' - NC='\033[0m' - - project="{{project}}" - tag="{{tag}}" - - # Load environment variables from .env file - if [ -f ".env" ]; then - source .env - else - echo -e "${RED}Error: .env file not found${NC}" >&2 - echo "Create .env file with your GitHub credentials" >&2 - exit 1 - fi - - # Check loaded variables - if [ -z "${GITHUB_USERNAME:-}" ]; then - echo -e "${RED}Error: GITHUB_USERNAME not set in .env file${NC}" >&2 - exit 1 - fi - - # Detect runtime - runtime=$(just _detect_runtime) - - # Create full image name - full_image_name="{{REGISTRY}}/$GITHUB_USERNAME/$project:$tag" - - echo -e "${BLUE}Pulling $project:$tag from registry...${NC}" - - $runtime pull "$full_image_name" - - # Tag locally for convenience - $runtime tag "$full_image_name" "$project:$tag" - - echo -e "${GREEN}✓ Image pulled successfully: $full_image_name${NC}" - echo -e "${GREEN}✓ Tagged locally as: $project:$tag${NC}" - -# Tag any project's existing image -image-tag project new_tag: - #!/usr/bin/env bash - set -euo pipefail - - # Colors - GREEN='\033[0;32m' - BLUE='\033[0;34m' - RED='\033[0;31m' - NC='\033[0m' - - project="{{project}}" - new_tag="{{new_tag}}" - - # Detect runtime - runtime=$(just _detect_runtime) - - echo -e "${BLUE}Tagging $project:latest as $project:$new_tag${NC}" - - $runtime tag "$project:latest" "$project:$new_tag" - - # Also create registry tag if username is set - if [ -n "${GITHUB_USERNAME:-}" ]; then - registry_tag="{{REGISTRY}}/$GITHUB_USERNAME/$project:$new_tag" - $runtime tag "$project:latest" "$registry_tag" - echo -e "${GREEN}✓ Tagged as: $project:$new_tag and $registry_tag${NC}" - else - echo -e "${GREEN}✓ Tagged as: $project:$new_tag${NC}" - fi - -# Test any project's image -image-test project tag="latest": - #!/usr/bin/env bash - set -euo pipefail - - # Colors - GREEN='\033[0;32m' - BLUE='\033[0;34m' - YELLOW='\033[1;33m' - RED='\033[0;31m' - NC='\033[0m' - - project="{{project}}" - tag="{{tag}}" - runtime=$(just _detect_runtime) - - echo -e "${BLUE}Testing $project image: $project:$tag${NC}" - - # Check if image exists - if ! $runtime images "$project:$tag" | grep -q "$project"; then - echo -e "${RED}Error: Image $project:$tag not found${NC}" >&2 - echo "Build it first with: just image-build $project $tag" >&2 - exit 1 - fi - - echo -e "${YELLOW}Starting temporary $project container for testing...${NC}" - - # Run temporary container - container_id=$($runtime run -d --rm "$project:$tag" sleep 30) - - echo "Container ID: $container_id" - - # Wait for container to start - sleep 5 - - # Basic test - check if container is running - if $runtime exec "$container_id" echo "Container is responsive" >/dev/null 2>&1; then - echo -e "${GREEN}✓ Container is responsive${NC}" - else - echo -e "${RED}✗ Container test failed${NC}" - fi - - # Cleanup - echo -e "${YELLOW}Cleaning up test container...${NC}" - $runtime stop "$container_id" >/dev/null 2>&1 - - echo -e "${GREEN}✓ $project image test completed${NC}" - -# Show any project's image information -image-info project tag="latest": - #!/usr/bin/env bash - set -euo pipefail - - # Colors - BLUE='\033[0;34m' - GREEN='\033[0;32m' - NC='\033[0m' - - project="{{project}}" - tag="{{tag}}" - runtime=$(just _detect_runtime) - - echo -e "${BLUE}$project Image Information: $project:$tag${NC}" - echo "" - - if $runtime images "$project:$tag" | grep -q "$project"; then - echo -e "${GREEN}Image Details:${NC}" - $runtime images "$project:$tag" - echo "" - - echo -e "${GREEN}Image History (last 10 layers):${NC}" - $runtime history "$project:$tag" | head -10 - else - echo "Image $project:$tag not found locally" - echo "Build it with: just image-build $project $tag" - fi - -# List all project images -[group('images')] -images-list: - #!/usr/bin/env bash - set -euo pipefail - - # Colors - BLUE='\033[0;34m' - NC='\033[0m' - - runtime=$(just _detect_runtime) - - echo -e "${BLUE}Local Project Images:${NC}" - - # List images for known projects - for project in postgres servapp; do - if [ -d "$project" ]; then - echo -e "\n${BLUE}$project images:${NC}" - $runtime images "$project" 2>/dev/null || echo " No images found" - fi - done - - # List any other images that might be project images - echo -e "\n${BLUE}Registry images:${NC}" - if [ -n "${GITHUB_USERNAME:-}" ]; then - $runtime images | grep "{{REGISTRY}}/$GITHUB_USERNAME" || echo " No registry images found" - else - echo " Set GITHUB_USERNAME to see registry images" - fi - -# Remove any project's local images -image-clean project: - #!/usr/bin/env bash - set -euo pipefail - - # Colors - GREEN='\033[0;32m' - BLUE='\033[0;34m' - YELLOW='\033[1;33m' - RED='\033[0;31m' - NC='\033[0m' - - project="{{project}}" - - runtime=$(just _detect_runtime) - - echo -e "${YELLOW}Removing all local images for: $project${NC}" - - # Remove local tags (disable pipefail temporarily for this section) - set +e - - # Remove common local project tags - for tag in latest commit-* build-*; do - $runtime rmi "$project:$tag" 2>/dev/null || true - $runtime rmi "localhost/$project:$tag" 2>/dev/null || true - $runtime rmi "localhost/${project}_${project}:$tag" 2>/dev/null || true - done - - # Remove all images matching project name patterns - $runtime images --format "\{\{.Repository\}\}:\{\{.Tag\}\}" | grep -E "^($project|localhost/$project|localhost/${project}_${project})" | while read -r img; do - [ -n "$img" ] && $runtime rmi "$img" 2>/dev/null || true - done - - # Remove registry tags if they exist - if [ -n "${GITHUB_USERNAME:-}" ]; then - $runtime images --format "\{\{.Repository\}\}:\{\{.Tag\}\}" | grep "{{REGISTRY}}/$GITHUB_USERNAME/$project" | while read -r img; do - [ -n "$img" ] && $runtime rmi "$img" 2>/dev/null || true - done - fi - - # Re-enable strict error handling - set -e - - echo -e "${GREEN}✓ Cleaned local images for: $project${NC}" - -# Quick build all known projects -images-build-all: - @echo "{{BLUE}}Building all known projects...{{NC}}" - @just image-build postgres - @just image-build servapp - @echo "{{GREEN}}✓ All projects built successfully{{NC}}" - -# Quick push all known projects -images-push-all tag=DEFAULT_TAG: - @echo "{{BLUE}}Pushing all known projects with tag: {{tag}}{{NC}}" - @just image-push postgres {{tag}} - @just image-push servapp {{tag}} - @echo "{{GREEN}}✓ All projects pushed successfully{{NC}}" \ No newline at end of file diff --git a/images/mod.just b/images/mod.just new file mode 100644 index 0000000..efe2852 --- /dev/null +++ b/images/mod.just @@ -0,0 +1,294 @@ +# Universal container image operations + +# Build project image +[group('images')] +build project tag="": + #!/usr/bin/env bash + set -euo pipefail + + project="{{project}}" + tag="{{tag}}" + + if [ -z "$project" ]; then + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} Project name is required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just images build myproject [tag]" >&2 + exit 1 + fi + + # Check if project directory exists + if [ ! -d "$project" ]; then + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} Project directory '$project' not found" >&2 + exit 1 + fi + + # Check for Containerfile or Dockerfile + containerfile="" + if [ -f "$project/Containerfile" ]; then + containerfile="$project/Containerfile" + elif [ -f "$project/Dockerfile" ]; then + containerfile="$project/Dockerfile" + else + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} No Containerfile or Dockerfile found in $project/" >&2 + exit 1 + fi + + # Generate tag if not provided + if [ -z "$tag" ]; then + if git rev-parse --git-dir >/dev/null 2>&1; then + tag="commit-$(git rev-parse --short HEAD)" + else + tag="build-$(date '+%Y%m%d-%H%M%S')" + fi + fi + + runtime=$(just _detect_runtime) + registry="${REGISTRY:-ghcr.io}" + username="${GITHUB_USERNAME:-}" + + if [ -n "$username" ]; then + image_name="$registry/$username/$project:$tag" + else + image_name="$project:$tag" + fi + + echo -e "{{BLUE}}Building image: $image_name{{NORMAL}}" + echo -e "{{YELLOW}}Using: $containerfile{{NORMAL}}" + + $runtime build -f "$containerfile" -t "$image_name" "$project/" + + echo -e "{{GREEN}}✓ Successfully built: $image_name{{NORMAL}}" + +# Push project image to registry +[group('images')] +push project tag="": + #!/usr/bin/env bash + set -euo pipefail + + project="{{project}}" + tag="{{tag}}" + + if [ -z "$project" ]; then + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} Project name is required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just images push myproject [tag]" >&2 + exit 1 + fi + + # Generate tag if not provided + if [ -z "$tag" ]; then + if git rev-parse --git-dir >/dev/null 2>&1; then + tag="commit-$(git rev-parse --short HEAD)" + else + tag="latest" + fi + fi + + runtime=$(just _detect_runtime) + registry="${REGISTRY:-ghcr.io}" + username="${GITHUB_USERNAME:-}" + + if [ -z "$username" ]; then + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} GITHUB_USERNAME not set" >&2 + echo "{{YELLOW}}Set GITHUB_USERNAME in .env file{{NORMAL}}" >&2 + exit 1 + fi + + image_name="$registry/$username/$project:$tag" + + echo -e "{{BLUE}}Pushing image: $image_name{{NORMAL}}" + $runtime push "$image_name" + + echo -e "{{GREEN}}✓ Successfully pushed: $image_name{{NORMAL}}" + +# Pull project image from registry +[group('images')] +pull project tag="latest": + #!/usr/bin/env bash + set -euo pipefail + + project="{{project}}" + tag="{{tag}}" + + if [ -z "$project" ]; then + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} Project name is required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just images pull myproject [tag]" >&2 + exit 1 + fi + + runtime=$(just _detect_runtime) + registry="${REGISTRY:-ghcr.io}" + username="${GITHUB_USERNAME:-}" + + if [ -z "$username" ]; then + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} GITHUB_USERNAME not set" >&2 + echo "{{YELLOW}}Set GITHUB_USERNAME in .env file{{NORMAL}}" >&2 + exit 1 + fi + + image_name="$registry/$username/$project:$tag" + + echo -e "{{BLUE}}Pulling image: $image_name{{NORMAL}}" + $runtime pull "$image_name" + + echo -e "{{GREEN}}✓ Successfully pulled: $image_name{{NORMAL}}" + +# Tag existing image +[group('images')] +tag project new_tag: + #!/usr/bin/env bash + set -euo pipefail + + project="{{project}}" + new_tag="{{new_tag}}" + + if [ -z "$project" ] || [ -z "$new_tag" ]; then + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} Project name and new tag are required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just images tag myproject newtag" >&2 + exit 1 + fi + + runtime=$(just _detect_runtime) + registry="${REGISTRY:-ghcr.io}" + username="${GITHUB_USERNAME:-}" + + if [ -n "$username" ]; then + old_image="$registry/$username/$project" + new_image="$registry/$username/$project:$new_tag" + else + old_image="$project" + new_image="$project:$new_tag" + fi + + # Find the most recent tag for the project + latest_image=$($runtime images --format "table {{{{.Repository}}}}:{{{{.Tag}}}}" | grep "^$old_image" | head -1) + + if [ -z "$latest_image" ]; then + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} No images found for project: $project" >&2 + exit 1 + fi + + echo -e "{{BLUE}}Tagging image: $latest_image → $new_image{{NORMAL}}" + $runtime tag "$latest_image" "$new_image" + + echo -e "{{GREEN}}✓ Successfully tagged: $new_image{{NORMAL}}" + +# Show image information +[group('images')] +info project tag="": + #!/usr/bin/env bash + set -euo pipefail + + project="{{project}}" + tag="{{tag}}" + + if [ -z "$project" ]; then + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} Project name is required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just images info myproject [tag]" >&2 + exit 1 + fi + + runtime=$(just _detect_runtime) + registry="${REGISTRY:-ghcr.io}" + username="${GITHUB_USERNAME:-}" + + if [ -n "$username" ]; then + image_base="$registry/$username/$project" + else + image_base="$project" + fi + + if [ -n "$tag" ]; then + image_name="$image_base:$tag" + else + image_name="$image_base" + fi + + echo -e "{{BLUE}}Image information for: $image_name{{NORMAL}}" + echo "" + + # Show image details + $runtime images "$image_name" --format "table {{{{.Repository}}}}\\t{{{{.Tag}}}}\\t{{{{.ID}}}}\\t{{{{.CreatedSince}}}}\\t{{{{.Size}}}}" + + echo "" + echo -e "{{BLUE}}Image history:{{NORMAL}}" + $runtime history "$image_name" 2>/dev/null || echo "Image not found locally" + +# Remove project images +[group('images')] +[confirm] +clean project: + #!/usr/bin/env bash + set -euo pipefail + + project="{{project}}" + + if [ -z "$project" ]; then + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} Project name is required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just images clean myproject" >&2 + exit 1 + fi + + runtime=$(just _detect_runtime) + registry="${REGISTRY:-ghcr.io}" + username="${GITHUB_USERNAME:-}" + + if [ -n "$username" ]; then + image_pattern="$registry/$username/$project" + else + image_pattern="$project" + fi + + echo -e "{{YELLOW}}Removing all images for project: $project{{NORMAL}}" + + # Find and remove all images for the project + images=$($runtime images --format "{{{{.Repository}}}}:{{{{.Tag}}}}" | grep "^$image_pattern" || true) + + if [ -z "$images" ]; then + echo -e "{{YELLOW}}No images found for project: $project{{NORMAL}}" + exit 0 + fi + + echo -e "{{BLUE}}Images to remove:{{NORMAL}}" + echo "$images" + echo "" + + echo "$images" | while IFS= read -r image; do + if [ -n "$image" ]; then + echo -e "{{BLUE}}Removing: $image{{NORMAL}}" + $runtime rmi "$image" 2>/dev/null || true + fi + done + + echo -e "{{GREEN}}✓ Project images cleaned{{NORMAL}}" + +# Build all known projects +[group('images')] +build-all: + #!/usr/bin/env bash + set -euo pipefail + + echo -e "{{BLUE}}Building all projects with Containerfiles...{{NORMAL}}" + + # Find all directories with Containerfile or Dockerfile + projects="" + for dir in */; do + if [ -f "${dir}Containerfile" ] || [ -f "${dir}Dockerfile" ]; then + project_name="${dir%/}" + projects="$projects $project_name" + fi + done + + if [ -z "$projects" ]; then + echo -e "{{YELLOW}}No projects with Containerfile/Dockerfile found{{NORMAL}}" + exit 0 + fi + + echo -e "{{BLUE}}Found projects:$projects{{NORMAL}}" + echo "" + + for project in $projects; do + echo -e "{{CYAN}}Building project: $project{{NORMAL}}" + just images build "$project" + echo "" + done + + echo -e "{{GREEN}}✓ All projects built successfully{{NORMAL}}" \ No newline at end of file diff --git a/justfile b/justfile new file mode 100644 index 0000000..9b826c0 --- /dev/null +++ b/justfile @@ -0,0 +1,106 @@ +# Just Commons - Universal Command Library with Modern Module Architecture +# Version 2.0 - Full Module Migration + +# Import core utilities (shared functions) +import 'core.just' + +# Declare optional modules - projects can use only what they need +mod? postgres 'postgres' +mod? mysql 'mysql' +mod? volumes 'volumes' +mod? container 'container' +mod? registry 'registry' +mod? images 'images' + +# Default recipe - show available modules and commands +[group('help')] +default: + @echo "{{BOLD}}{{CYAN}}Just Commons - Universal Command Library{{NORMAL}}" + @echo "{{BLUE}}Version 2.0 - Modern Module Architecture{{NORMAL}}" + @echo "" + @echo "{{BOLD}}Available Modules:{{NORMAL}}" + @echo " {{YELLOW}}container{{NORMAL}} - Universal container operations (start, stop, logs, shell, exec)" + @echo " {{YELLOW}}postgres{{NORMAL}} - PostgreSQL database operations (sql, check, create-database, etc.)" + @echo " {{YELLOW}}mysql{{NORMAL}} - MySQL database operations (sql, check, create-database, etc.)" + @echo " {{YELLOW}}volumes{{NORMAL}} - Volume management (clean-all, remove, list)" + @echo " {{YELLOW}}images{{NORMAL}} - Image operations (build, push, pull, tag, info, clean)" + @echo " {{YELLOW}}registry{{NORMAL}} - Registry authentication (login, logout, check)" + @echo "" + @echo "{{BOLD}}Usage Examples:{{NORMAL}}" + @echo " {{GREEN}}just container start postgres{{NORMAL}} # Start PostgreSQL service" + @echo " {{GREEN}}just postgres sql \"SELECT version();\"{{NORMAL}} # Execute SQL query" + @echo " {{GREEN}}just volumes list\"myproject_*\"{{NORMAL}} # List project volumes" + @echo " {{GREEN}}just images build myapp{{NORMAL}} # Build application image" + @echo " {{GREEN}}just registry login{{NORMAL}} # Login to container registry" + @echo "" + @echo "{{BOLD}}Environment Check:{{NORMAL}}" + @echo " {{GREEN}}just env-check{{NORMAL}} # Verify container runtime availability" + @echo "" + @echo "{{BLUE}}For detailed command lists, run:{{NORMAL}} {{CYAN}}just --list{{NORMAL}}" + +# Show module-specific help +[group('help')] +help module: + #!/usr/bin/env bash + module="{{module}}" + + case "$module" in + "container") + echo "{{BOLD}}{{CYAN}}Container Module Commands:{{NORMAL}}" + echo " {{YELLOW}}start [service] [compose-file]{{NORMAL}} - Start services" + echo " {{YELLOW}}stop [service] [compose-file]{{NORMAL}} - Stop services" + echo " {{YELLOW}}restart [service] [compose-file]{{NORMAL}} - Restart services" + echo " {{YELLOW}}status [service] [compose-file]{{NORMAL}} - Show service status" + echo " {{YELLOW}}logs [service] [compose-file]{{NORMAL}} - View service logs" + echo " {{YELLOW}}shell [compose-file]{{NORMAL}} - Open shell in container" + echo " {{YELLOW}}exec [compose-file]{{NORMAL}} - Execute command" + ;; + "postgres") + echo "{{BOLD}}{{CYAN}}PostgreSQL Module Commands:{{NORMAL}}" + echo " {{YELLOW}}sql [service] [compose-file]{{NORMAL}} - Execute SQL query" + echo " {{YELLOW}}check [service] [compose-file]{{NORMAL}} - Check connection" + echo " {{YELLOW}}list-databases [service] [compose-file]{{NORMAL}} - List databases" + echo " {{YELLOW}}create-database [service]{{NORMAL}} - Create database" + echo " {{YELLOW}}drop-database [service]{{NORMAL}} - Drop database (with confirmation)" + echo " {{YELLOW}}shell [service] [compose-file]{{NORMAL}} - Interactive shell" + echo " {{YELLOW}}restore [service] [compose-file]{{NORMAL}} - Restore from backup" + ;; + "mysql") + echo "{{BOLD}}{{CYAN}}MySQL Module Commands:{{NORMAL}}" + echo " {{YELLOW}}sql [service] [compose-file]{{NORMAL}} - Execute SQL query" + echo " {{YELLOW}}check [service] [compose-file]{{NORMAL}} - Check connection" + echo " {{YELLOW}}list-databases [service] [compose-file]{{NORMAL}} - List databases" + echo " {{YELLOW}}create-database [service]{{NORMAL}} - Create database" + echo " {{YELLOW}}drop-database [service]{{NORMAL}} - Drop database (with confirmation)" + echo " {{YELLOW}}create-user [service]{{NORMAL}} - Create user" + echo " {{YELLOW}}grant-privileges [service]{{NORMAL}} - Grant privileges" + echo " {{YELLOW}}shell [service] [compose-file]{{NORMAL}} - Interactive shell" + ;; + "volumes") + echo "{{BOLD}}{{CYAN}}Volumes Module Commands:{{NORMAL}}" + echo " {{YELLOW}}clean-all [compose-file]{{NORMAL}} - Remove all compose volumes (with confirmation)" + echo " {{YELLOW}}remove {{NORMAL}} - Remove specific volume (with confirmation)" + echo " {{YELLOW}}remove-pattern {{NORMAL}} - Remove volumes matching pattern (with confirmation)" + echo " {{YELLOW}}list [pattern]{{NORMAL}} - List volumes (optionally filtered)" + ;; + "images") + echo "{{BOLD}}{{CYAN}}Images Module Commands:{{NORMAL}}" + echo " {{YELLOW}}build [tag]{{NORMAL}} - Build project image" + echo " {{YELLOW}}push [tag]{{NORMAL}} - Push image to registry" + echo " {{YELLOW}}pull [tag]{{NORMAL}} - Pull image from registry" + echo " {{YELLOW}}tag {{NORMAL}} - Tag existing image" + echo " {{YELLOW}}info [tag]{{NORMAL}} - Show image information" + echo " {{YELLOW}}clean {{NORMAL}} - Remove project images (with confirmation)" + echo " {{YELLOW}}build-all{{NORMAL}} - Build all projects with Containerfiles" + ;; + "registry") + echo "{{BOLD}}{{CYAN}}Registry Module Commands:{{NORMAL}}" + echo " {{YELLOW}}login{{NORMAL}} - Login to container registry" + echo " {{YELLOW}}logout{{NORMAL}} - Logout from registry" + echo " {{YELLOW}}check{{NORMAL}} - Check authentication status" + ;; + *) + echo "{{BOLD}}{{RED}}Unknown module: $module{{NORMAL}}" + echo "{{YELLOW}}Available modules:{{NORMAL}} container, postgres, mysql, volumes, images, registry" + ;; + esac \ No newline at end of file diff --git a/mysql.just b/mysql/mod.just similarity index 73% rename from mysql.just rename to mysql/mod.just index da99c37..fd86d61 100644 --- a/mysql.just +++ b/mysql/mod.just @@ -1,7 +1,8 @@ # Universal MySQL database operations # Execute MySQL SQL query -mysql-sql query service="mysql" compose-file="": +[group('database')] +sql query service="mysql" compose-file="": #!/usr/bin/env bash set -euo pipefail @@ -10,8 +11,8 @@ mysql-sql query service="mysql" compose-file="": compose_file="{{compose-file}}" if [ -z "$query" ]; then - echo "Error: SQL query is required" >&2 - echo "Usage: just mysql-sql \"SELECT VERSION();\"" >&2 + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} SQL query is required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just mysql sql \"SELECT VERSION();\"" >&2 exit 1 fi @@ -21,8 +22,8 @@ mysql-sql query service="mysql" compose-file="": file_arg="$compose_file" fi - echo -e "{{BLUE}}Executing MySQL query in service: $service{{NC}}" - echo -e "{{YELLOW}}Query: $query{{NC}}" + echo -e "{{BLUE}}Executing MySQL query in service: $service{{NORMAL}}" + echo -e "{{YELLOW}}Query: $query{{NORMAL}}" if [ -n "$file_arg" ]; then just exec "$service" "mysql -u root -p\${MYSQL_ROOT_PASSWORD} -e \"$query\"" "$file_arg" @@ -31,7 +32,8 @@ mysql-sql query service="mysql" compose-file="": fi # Check MySQL connection and status -mysql-check service="mysql" compose-file="": +[group('database')] +check service="mysql" compose-file="": #!/usr/bin/env bash set -euo pipefail @@ -44,7 +46,7 @@ mysql-check service="mysql" compose-file="": file_arg="$compose_file" fi - echo -e "{{BLUE}}Checking MySQL status in service: $service{{NC}}" + echo -e "{{BLUE}}Checking MySQL status in service: $service{{NORMAL}}" if [ -n "$file_arg" ]; then just exec "$service" "mysqladmin -u root -p\${MYSQL_ROOT_PASSWORD} ping" "$file_arg" @@ -55,7 +57,8 @@ mysql-check service="mysql" compose-file="": fi # List MySQL databases -mysql-list-databases service="mysql" compose-file="": +[group('database')] +list-databases service="mysql" compose-file="": #!/usr/bin/env bash set -euo pipefail @@ -68,7 +71,7 @@ mysql-list-databases service="mysql" compose-file="": file_arg="$compose_file" fi - echo -e "{{BLUE}}Listing MySQL databases in service: $service{{NC}}" + echo -e "{{BLUE}}Listing MySQL databases in service: $service{{NORMAL}}" if [ -n "$file_arg" ]; then just exec "$service" "mysql -u root -p\${MYSQL_ROOT_PASSWORD} -e 'SHOW DATABASES;'" "$file_arg" @@ -77,7 +80,8 @@ mysql-list-databases service="mysql" compose-file="": fi # List MySQL users -mysql-list-users service="mysql" compose-file="": +[group('database')] +list-users service="mysql" compose-file="": #!/usr/bin/env bash set -euo pipefail @@ -90,7 +94,7 @@ mysql-list-users service="mysql" compose-file="": file_arg="$compose_file" fi - echo -e "{{BLUE}}Listing MySQL users in service: $service{{NC}}" + echo -e "{{BLUE}}Listing MySQL users in service: $service{{NORMAL}}" if [ -n "$file_arg" ]; then just exec "$service" "mysql -u root -p\${MYSQL_ROOT_PASSWORD} -e 'SELECT User, Host FROM mysql.user;'" "$file_arg" @@ -99,7 +103,8 @@ mysql-list-users service="mysql" compose-file="": fi # Create MySQL database -mysql-create-database database service="mysql" compose-file="": +[group('database')] +create-database database service="mysql" compose-file="": #!/usr/bin/env bash set -euo pipefail @@ -108,8 +113,8 @@ mysql-create-database database service="mysql" compose-file="": compose_file="{{compose-file}}" if [ -z "$database" ]; then - echo "Error: Database name is required" >&2 - echo "Usage: just mysql-create-database mydb" >&2 + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} Database name is required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just mysql create-database mydb" >&2 exit 1 fi @@ -119,7 +124,7 @@ mysql-create-database database service="mysql" compose-file="": file_arg="$compose_file" fi - echo -e "{{BLUE}}Creating MySQL database: $database{{NC}}" + echo -e "{{BLUE}}Creating MySQL database: $database{{NORMAL}}" if [ -n "$file_arg" ]; then just exec "$service" "mysql -u root -p\${MYSQL_ROOT_PASSWORD} -e 'CREATE DATABASE \`$database\`;'" "$file_arg" @@ -128,8 +133,9 @@ mysql-create-database database service="mysql" compose-file="": fi # Drop MySQL database +[group('database')] [confirm] -mysql-drop-database database service="mysql" compose-file="": +drop-database database service="mysql" compose-file="": #!/usr/bin/env bash set -euo pipefail @@ -138,8 +144,8 @@ mysql-drop-database database service="mysql" compose-file="": compose_file="{{compose-file}}" if [ -z "$database" ]; then - echo "Error: Database name is required" >&2 - echo "Usage: just mysql-drop-database mydb" >&2 + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} Database name is required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just mysql drop-database mydb" >&2 exit 1 fi @@ -149,8 +155,8 @@ mysql-drop-database database service="mysql" compose-file="": file_arg="$compose_file" fi - echo -e "{{YELLOW}}WARNING: This will permanently delete database: $database{{NC}}" - echo -e "{{BLUE}}Dropping MySQL database: $database{{NC}}" + echo -e "{{YELLOW}}WARNING: This will permanently delete database: $database{{NORMAL}}" + echo -e "{{BLUE}}Dropping MySQL database: $database{{NORMAL}}" if [ -n "$file_arg" ]; then just exec "$service" "mysql -u root -p\${MYSQL_ROOT_PASSWORD} -e 'DROP DATABASE \`$database\`;'" "$file_arg" @@ -159,7 +165,8 @@ mysql-drop-database database service="mysql" compose-file="": fi # Create MySQL user -mysql-create-user username password service="mysql" compose-file="": +[group('database')] +create-user username password service="mysql" compose-file="": #!/usr/bin/env bash set -euo pipefail @@ -169,8 +176,8 @@ mysql-create-user username password service="mysql" compose-file="": compose_file="{{compose-file}}" if [ -z "$username" ] || [ -z "$password" ]; then - echo "Error: Username and password are required" >&2 - echo "Usage: just mysql-create-user myuser mypassword" >&2 + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} Username and password are required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just mysql create-user myuser mypassword" >&2 exit 1 fi @@ -180,7 +187,7 @@ mysql-create-user username password service="mysql" compose-file="": file_arg="$compose_file" fi - echo -e "{{BLUE}}Creating MySQL user: $username{{NC}}" + echo -e "{{BLUE}}Creating MySQL user: $username{{NORMAL}}" if [ -n "$file_arg" ]; then just exec "$service" "mysql -u root -p\${MYSQL_ROOT_PASSWORD} -e \"CREATE USER '$username'@'%' IDENTIFIED BY '$password';\"" "$file_arg" @@ -189,7 +196,8 @@ mysql-create-user username password service="mysql" compose-file="": fi # Grant MySQL privileges -mysql-grant-privileges database username service="mysql" compose-file="": +[group('database')] +grant-privileges database username service="mysql" compose-file="": #!/usr/bin/env bash set -euo pipefail @@ -199,8 +207,8 @@ mysql-grant-privileges database username service="mysql" compose-file="": compose_file="{{compose-file}}" if [ -z "$database" ] || [ -z "$username" ]; then - echo "Error: Database and username are required" >&2 - echo "Usage: just mysql-grant-privileges mydb myuser" >&2 + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} Database and username are required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just mysql grant-privileges mydb myuser" >&2 exit 1 fi @@ -210,7 +218,7 @@ mysql-grant-privileges database username service="mysql" compose-file="": file_arg="$compose_file" fi - echo -e "{{BLUE}}Granting privileges on $database to $username{{NC}}" + echo -e "{{BLUE}}Granting privileges on $database to $username{{NORMAL}}" if [ -n "$file_arg" ]; then just exec "$service" "mysql -u root -p\${MYSQL_ROOT_PASSWORD} -e \"GRANT ALL PRIVILEGES ON \\\`$database\\\`.* TO '$username'@'%'; FLUSH PRIVILEGES;\"" "$file_arg" @@ -219,7 +227,8 @@ mysql-grant-privileges database username service="mysql" compose-file="": fi # MySQL interactive shell -mysql-shell service="mysql" compose-file="": +[group('database')] +shell service="mysql" compose-file="": #!/usr/bin/env bash set -euo pipefail @@ -232,7 +241,7 @@ mysql-shell service="mysql" compose-file="": file_arg="$compose_file" fi - echo -e "{{BLUE}}Opening MySQL interactive shell in service: $service{{NC}}" + echo -e "{{BLUE}}Opening MySQL interactive shell in service: $service{{NORMAL}}" if [ -n "$file_arg" ]; then just exec "$service" "mysql -u root -p\${MYSQL_ROOT_PASSWORD}" "$file_arg" @@ -243,7 +252,7 @@ mysql-shell service="mysql" compose-file="": # Restore MySQL database from backup file [group('database')] [confirm] -mysql-restore backup_file database service="mysql" compose-file="" backup_path="./backups": +restore backup_file database service="mysql" compose-file="" backup_path="./backups": #!/usr/bin/env bash set -euo pipefail @@ -254,8 +263,8 @@ mysql-restore backup_file database service="mysql" compose-file="" backup_path=" backup_path="{{backup_path}}" if [ -z "$backup_file" ] || [ -z "$database" ]; then - echo "Error: Backup file and database name are required" >&2 - echo "Usage: just mysql-restore backup_file.sql database_name" >&2 + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} Backup file and database name are required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just mysql restore backup_file.sql database_name" >&2 exit 1 fi @@ -267,38 +276,38 @@ mysql-restore backup_file database service="mysql" compose-file="" backup_path=" # Check if backup file exists if [ ! -f "$backup_path/$backup_file" ]; then - echo -e "{{RED}}Error: Backup file '$backup_path/$backup_file' not found{{NC}}" >&2 - echo -e "{{YELLOW}}Available backups:{{NC}}" + echo -e "{{RED}}Error: Backup file '$backup_path/$backup_file' not found{{NORMAL}}" >&2 + echo -e "{{YELLOW}}Available backups:{{NORMAL}}" ls -la "$backup_path/" 2>/dev/null || echo "No backups directory found at $backup_path" exit 1 fi # Display backup file info - echo -e "{{BLUE}}Backup file information:{{NC}}" - echo -e "{{YELLOW}}File:{{NC}} $backup_path/$backup_file" - echo -e "{{YELLOW}}Size:{{NC}} $(du -h "$backup_path/$backup_file" | cut -f1)" - echo -e "{{YELLOW}}Modified:{{NC}} $(stat -c %y "$backup_path/$backup_file" 2>/dev/null || stat -f %Sm "$backup_path/$backup_file")" + echo -e "{{BLUE}}Backup file information:{{NORMAL}}" + echo -e "{{YELLOW}}File:{{NORMAL}} $backup_path/$backup_file" + echo -e "{{YELLOW}}Size:{{NORMAL}} $(du -h "$backup_path/$backup_file" | cut -f1)" + echo -e "{{YELLOW}}Modified:{{NORMAL}} $(stat -c %y "$backup_path/$backup_file" 2>/dev/null || stat -f %Sm "$backup_path/$backup_file")" echo "" # Detect backup type if [[ "$backup_file" == *.gz ]]; then backup_type="gzipped SQL" - echo -e "{{BLUE}}Backup type:{{NC}} $backup_type" + echo -e "{{BLUE}}Backup type:{{NORMAL}} $backup_type" else backup_type="plain SQL" - echo -e "{{BLUE}}Backup type:{{NC}} $backup_type" + echo -e "{{BLUE}}Backup type:{{NORMAL}} $backup_type" fi - echo -e "{{BLUE}}Target database:{{NC}} $database" - echo -e "{{BLUE}}Target service:{{NC}} $service" + echo -e "{{BLUE}}Target database:{{NORMAL}} $database" + echo -e "{{BLUE}}Target service:{{NORMAL}} $service" echo "" - echo -e "{{RED}}⚠️ WARNING: This will OVERWRITE the current database!{{NC}}" - echo -e "{{YELLOW}}This action will replace all data in '$database' database{{NC}}" - echo -e "{{YELLOW}}Make sure you have a backup of current data if needed{{NC}}" + echo -e "{{RED}}⚠️ WARNING: This will OVERWRITE the current database!{{NORMAL}}" + echo -e "{{YELLOW}}This action will replace all data in '$database' database{{NORMAL}}" + echo -e "{{YELLOW}}Make sure you have a backup of current data if needed{{NORMAL}}" echo "" - echo -e "{{BLUE}}Restoring database '$database' from $backup_file...{{NC}}" + echo -e "{{BLUE}}Restoring database '$database' from $backup_file...{{NORMAL}}" # Restore database from backup file if [[ "$backup_file" == *.gz ]]; then @@ -317,4 +326,4 @@ mysql-restore backup_file database service="mysql" compose-file="" backup_path=" fi fi - echo -e "{{GREEN}}✓ Database '$database' restored successfully from $backup_file{{NC}}" \ No newline at end of file + echo -e "{{GREEN}}✓ Database '$database' restored successfully from $backup_file{{NORMAL}}" \ No newline at end of file diff --git a/postgres.just b/postgres/mod.just similarity index 72% rename from postgres.just rename to postgres/mod.just index 4fd038b..8267b63 100644 --- a/postgres.just +++ b/postgres/mod.just @@ -2,7 +2,7 @@ # Execute PostgreSQL SQL query [group('database')] -postgres-sql query service="postgres" compose-file="": +sql query service="postgres" compose-file="": #!/usr/bin/env bash set -euo pipefail @@ -11,8 +11,8 @@ postgres-sql query service="postgres" compose-file="": compose_file="{{compose-file}}" if [ -z "$query" ]; then - echo "Error: SQL query is required" >&2 - echo "Usage: just postgres-sql \"SELECT version();\"" >&2 + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} SQL query is required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just postgres sql \"SELECT version();\"" >&2 exit 1 fi @@ -22,8 +22,8 @@ postgres-sql query service="postgres" compose-file="": file_arg="$compose_file" fi - echo -e "{{BLUE}}Executing PostgreSQL query in service: $service{{NC}}" - echo -e "{{YELLOW}}Query: $query{{NC}}" + echo -e "{{BLUE}}Executing PostgreSQL query in service: $service{{NORMAL}}" + echo -e "{{YELLOW}}Query: $query{{NORMAL}}" if [ -n "$file_arg" ]; then just exec "$service" "psql -U postgres -c \"$query\"" "$file_arg" @@ -33,7 +33,7 @@ postgres-sql query service="postgres" compose-file="": # Check PostgreSQL connection and status [group('database')] -postgres-check service="postgres" compose-file="": +check service="postgres" compose-file="": #!/usr/bin/env bash set -euo pipefail @@ -46,7 +46,7 @@ postgres-check service="postgres" compose-file="": file_arg="$compose_file" fi - echo -e "{{BLUE}}Checking PostgreSQL status in service: $service{{NC}}" + echo -e "{{BLUE}}Checking PostgreSQL status in service: $service{{NORMAL}}" if [ -n "$file_arg" ]; then just exec "$service" "pg_isready -U postgres" "$file_arg" @@ -58,7 +58,7 @@ postgres-check service="postgres" compose-file="": # List PostgreSQL databases [group('database')] -postgres-list-databases service="postgres" compose-file="": +list-databases service="postgres" compose-file="": #!/usr/bin/env bash set -euo pipefail @@ -71,7 +71,7 @@ postgres-list-databases service="postgres" compose-file="": file_arg="$compose_file" fi - echo -e "{{BLUE}}Listing PostgreSQL databases in service: $service{{NC}}" + echo -e "{{BLUE}}Listing PostgreSQL databases in service: $service{{NORMAL}}" if [ -n "$file_arg" ]; then just exec "$service" "psql -U postgres -c '\\l'" "$file_arg" @@ -80,7 +80,8 @@ postgres-list-databases service="postgres" compose-file="": fi # List PostgreSQL users -postgres-list-users service="postgres" compose-file="": +[group('database')] +list-users service="postgres" compose-file="": #!/usr/bin/env bash set -euo pipefail @@ -93,7 +94,7 @@ postgres-list-users service="postgres" compose-file="": file_arg="$compose_file" fi - echo -e "{{BLUE}}Listing PostgreSQL users in service: $service{{NC}}" + echo -e "{{BLUE}}Listing PostgreSQL users in service: $service{{NORMAL}}" if [ -n "$file_arg" ]; then just exec "$service" "psql -U postgres -c '\\du'" "$file_arg" @@ -102,7 +103,8 @@ postgres-list-users service="postgres" compose-file="": fi # Create PostgreSQL database -postgres-create-database database service="postgres" compose-file="": +[group('database')] +create-database database service="postgres" compose-file="": #!/usr/bin/env bash set -euo pipefail @@ -111,8 +113,8 @@ postgres-create-database database service="postgres" compose-file="": compose_file="{{compose-file}}" if [ -z "$database" ]; then - echo "Error: Database name is required" >&2 - echo "Usage: just postgres-create-database mydb" >&2 + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} Database name is required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just postgres create-database mydb" >&2 exit 1 fi @@ -122,7 +124,7 @@ postgres-create-database database service="postgres" compose-file="": file_arg="$compose_file" fi - echo -e "{{BLUE}}Creating PostgreSQL database: $database{{NC}}" + echo -e "{{BLUE}}Creating PostgreSQL database: $database{{NORMAL}}" if [ -n "$file_arg" ]; then just exec "$service" "createdb -U postgres \"$database\"" "$file_arg" @@ -133,7 +135,7 @@ postgres-create-database database service="postgres" compose-file="": # Drop PostgreSQL database [group('database')] [confirm] -postgres-drop-database database service="postgres" compose-file="": +drop-database database service="postgres" compose-file="": #!/usr/bin/env bash set -euo pipefail @@ -142,8 +144,8 @@ postgres-drop-database database service="postgres" compose-file="": compose_file="{{compose-file}}" if [ -z "$database" ]; then - echo "Error: Database name is required" >&2 - echo "Usage: just postgres-drop-database mydb" >&2 + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} Database name is required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just postgres drop-database mydb" >&2 exit 1 fi @@ -153,8 +155,8 @@ postgres-drop-database database service="postgres" compose-file="": file_arg="$compose_file" fi - echo -e "{{YELLOW}}WARNING: This will permanently delete database: $database{{NC}}" - echo -e "{{BLUE}}Dropping PostgreSQL database: $database{{NC}}" + echo -e "{{YELLOW}}WARNING: This will permanently delete database: $database{{NORMAL}}" + echo -e "{{BLUE}}Dropping PostgreSQL database: $database{{NORMAL}}" if [ -n "$file_arg" ]; then just exec "$service" "dropdb -U postgres \"$database\"" "$file_arg" @@ -163,7 +165,8 @@ postgres-drop-database database service="postgres" compose-file="": fi # PostgreSQL interactive shell -postgres-shell service="postgres" compose-file="": +[group('database')] +shell service="postgres" compose-file="": #!/usr/bin/env bash set -euo pipefail @@ -176,7 +179,7 @@ postgres-shell service="postgres" compose-file="": file_arg="$compose_file" fi - echo -e "{{BLUE}}Opening PostgreSQL interactive shell in service: $service{{NC}}" + echo -e "{{BLUE}}Opening PostgreSQL interactive shell in service: $service{{NORMAL}}" if [ -n "$file_arg" ]; then just exec "$service" "psql -U postgres" "$file_arg" @@ -187,7 +190,7 @@ postgres-shell service="postgres" compose-file="": # Restore PostgreSQL database from backup file [group('database')] [confirm] -postgres-restore backup_file service="postgres" compose-file="" backup_path="./backups": +restore backup_file service="postgres" compose-file="" backup_path="./backups": #!/usr/bin/env bash set -euo pipefail @@ -197,8 +200,8 @@ postgres-restore backup_file service="postgres" compose-file="" backup_path="./b backup_path="{{backup_path}}" if [ -z "$backup_file" ]; then - echo "Error: Backup file name is required" >&2 - echo "Usage: just postgres-restore backup_file.sql" >&2 + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} Backup file name is required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just postgres restore backup_file.sql" >&2 exit 1 fi @@ -210,37 +213,37 @@ postgres-restore backup_file service="postgres" compose-file="" backup_path="./b # Check if backup file exists if [ ! -f "$backup_path/$backup_file" ]; then - echo -e "{{RED}}Error: Backup file '$backup_path/$backup_file' not found{{NC}}" >&2 - echo -e "{{YELLOW}}Available backups:{{NC}}" + echo -e "{{RED}}Error: Backup file '$backup_path/$backup_file' not found{{NORMAL}}" >&2 + echo -e "{{YELLOW}}Available backups:{{NORMAL}}" ls -la "$backup_path/" 2>/dev/null || echo "No backups directory found at $backup_path" exit 1 fi # Display backup file info - echo -e "{{BLUE}}Backup file information:{{NC}}" - echo -e "{{YELLOW}}File:{{NC}} $backup_path/$backup_file" - echo -e "{{YELLOW}}Size:{{NC}} $(du -h "$backup_path/$backup_file" | cut -f1)" - echo -e "{{YELLOW}}Modified:{{NC}} $(stat -c %y "$backup_path/$backup_file" 2>/dev/null || stat -f %Sm "$backup_path/$backup_file")" + echo -e "{{BLUE}}Backup file information:{{NORMAL}}" + echo -e "{{YELLOW}}File:{{NORMAL}} $backup_path/$backup_file" + echo -e "{{YELLOW}}Size:{{NORMAL}} $(du -h "$backup_path/$backup_file" | cut -f1)" + echo -e "{{YELLOW}}Modified:{{NORMAL}} $(stat -c %y "$backup_path/$backup_file" 2>/dev/null || stat -f %Sm "$backup_path/$backup_file")" echo "" # Detect backup type if [[ "$backup_file" == *.gz ]]; then backup_type="gzipped SQL" - echo -e "{{BLUE}}Backup type:{{NC}} $backup_type" + echo -e "{{BLUE}}Backup type:{{NORMAL}} $backup_type" else backup_type="plain SQL" - echo -e "{{BLUE}}Backup type:{{NC}} $backup_type" + echo -e "{{BLUE}}Backup type:{{NORMAL}} $backup_type" fi - echo -e "{{BLUE}}Target service:{{NC}} $service" + echo -e "{{BLUE}}Target service:{{NORMAL}} $service" echo "" - echo -e "{{RED}}⚠️ WARNING: This will OVERWRITE the current database!{{NC}}" - echo -e "{{YELLOW}}This action will replace all data in the target database{{NC}}" - echo -e "{{YELLOW}}Make sure you have a backup of current data if needed{{NC}}" + echo -e "{{RED}}⚠️ WARNING: This will OVERWRITE the current database!{{NORMAL}}" + echo -e "{{YELLOW}}This action will replace all data in the target database{{NORMAL}}" + echo -e "{{YELLOW}}Make sure you have a backup of current data if needed{{NORMAL}}" echo "" - echo -e "{{BLUE}}Restoring database from $backup_file...{{NC}}" + echo -e "{{BLUE}}Restoring database from $backup_file...{{NORMAL}}" # Copy backup file to container and restore if [[ "$backup_file" == *.gz ]]; then @@ -259,4 +262,4 @@ postgres-restore backup_file service="postgres" compose-file="" backup_path="./b fi fi - echo -e "{{GREEN}}✓ Database restored successfully from $backup_file{{NC}}" \ No newline at end of file + echo -e "{{GREEN}}✓ Database restored successfully from $backup_file{{NORMAL}}" \ No newline at end of file diff --git a/registry.just b/registry.just deleted file mode 100644 index c4851e4..0000000 --- a/registry.just +++ /dev/null @@ -1,175 +0,0 @@ -# Registry operations - -# Login to container registry -[group('registry')] -registry-login: - #!/usr/bin/env bash - set -euo pipefail - - # Colors - GREEN='\033[0;32m' - BLUE='\033[0;34m' - RED='\033[0;31m' - NC='\033[0m' - - # Load environment variables from .env file - if [ -f ".env" ]; then - source .env - else - echo -e "${RED}Error: .env file not found${NC}" >&2 - echo "Create .env file with:" >&2 - echo "GITHUB_USERNAME=your-username" >&2 - echo "GITHUB_TOKEN=your-token" >&2 - echo "Or copy from .env.example and modify" >&2 - exit 1 - fi - - # Check loaded variables - if [ -z "${GITHUB_USERNAME:-}" ]; then - echo -e "${RED}Error: GITHUB_USERNAME not set in .env file${NC}" >&2 - exit 1 - fi - - if [ -z "${GITHUB_TOKEN:-}" ]; then - echo -e "${RED}Error: GITHUB_TOKEN not set in .env file${NC}" >&2 - echo "Add your token to .env file: GITHUB_TOKEN=your-token" >&2 - exit 1 - fi - - # Detect runtime - runtime=$(just _detect_runtime) - - echo -e "${BLUE}Logging in to {{REGISTRY}} as $GITHUB_USERNAME...${NC}" - - if echo "$GITHUB_TOKEN" | $runtime login {{REGISTRY}} -u "$GITHUB_USERNAME" --password-stdin; then - echo -e "${GREEN}✓ Successfully logged in to {{REGISTRY}}${NC}" - else - echo -e "${RED}✗ Failed to login to {{REGISTRY}}${NC}" >&2 - exit 1 - fi - -# Logout from container registry -[group('registry')] -registry-logout: - #!/usr/bin/env bash - set -euo pipefail - - # Colors - GREEN='\033[0;32m' - BLUE='\033[0;34m' - NC='\033[0m' - - runtime=$(just _detect_runtime) - - echo -e "${BLUE}Logging out from {{REGISTRY}}...${NC}" - - $runtime logout {{REGISTRY}} - - echo -e "${GREEN}✓ Successfully logged out from {{REGISTRY}}${NC}" - - -# Check authentication and registry status -[group('registry')] -registry-check: - #!/usr/bin/env bash - set -euo pipefail - - # Colors - GREEN='\033[0;32m' - BLUE='\033[0;34m' - YELLOW='\033[1;33m' - RED='\033[0;31m' - NC='\033[0m' - - echo -e "${BLUE}=== Authentication Status ===${NC}" - echo "" - - # Check .env file and variables - echo -e "${BLUE}1. Environment Configuration (.env file):${NC}" - - if [ ! -f ".env" ]; then - echo -e "${RED} ✗ .env file not found${NC}" - echo " Edit .env file manually or copy from .env.example" - exit 1 - fi - - source .env - - if [ -n "${GITHUB_USERNAME:-}" ]; then - echo -e "${GREEN} ✓ GITHUB_USERNAME: $GITHUB_USERNAME${NC}" - else - echo -e "${RED} ✗ GITHUB_USERNAME: not set in .env${NC}" - echo " Add GITHUB_USERNAME=your-username to .env file" - exit 1 - fi - - if [ -n "${GITHUB_TOKEN:-}" ]; then - # Show masked token - token_len=${#GITHUB_TOKEN} - if [ $token_len -gt 8 ]; then - prefix=${GITHUB_TOKEN:0:4} - suffix=${GITHUB_TOKEN: -4} - masked_middle=$(printf "%*s" $((token_len-8)) | tr ' ' '*') - echo -e "${GREEN} ✓ GITHUB_TOKEN: ${prefix}${masked_middle}${suffix} (${token_len} chars)${NC}" - else - echo -e "${GREEN} ✓ GITHUB_TOKEN: $(printf "%*s" $token_len | tr ' ' '*') (${token_len} chars)${NC}" - fi - else - echo -e "${RED} ✗ GITHUB_TOKEN: not set in .env${NC}" - echo " Add GITHUB_TOKEN=your-token to .env file" - exit 1 - fi - echo "" - - # Check token validity - echo -e "${BLUE}2. GitHub API Authentication:${NC}" - response=$(curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user) - - if echo "$response" | grep -q '"login"'; then - username=$(echo "$response" | grep '"login"' | sed 's/.*"login": "\([^"]*\)".*/\1/') - echo -e "${GREEN} ✓ Token is valid - authenticated as: $username${NC}" - - # Check token scopes - scopes_response=$(curl -s -I -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user) - if echo "$scopes_response" | grep -i "x-oauth-scopes" > /dev/null; then - scopes=$(echo "$scopes_response" | grep -i "x-oauth-scopes" | cut -d: -f2- | tr -d '\r') - - # Check for required scopes - if echo "$scopes" | grep -q "write:packages"; then - echo -e "${GREEN} ✓ Has write:packages scope (push enabled)${NC}" - else - echo -e "${YELLOW} ⚠ Missing write:packages scope (push disabled)${NC}" - fi - - if echo "$scopes" | grep -q "read:packages"; then - echo -e "${GREEN} ✓ Has read:packages scope (pull enabled)${NC}" - else - echo -e "${YELLOW} ⚠ Missing read:packages scope (pull may fail)${NC}" - fi - fi - else - echo -e "${RED} ✗ Token is invalid or expired${NC}" - if echo "$response" | grep -q "Bad credentials"; then - echo " The token appears to be malformed or expired" - elif echo "$response" | grep -q "rate limit"; then - echo " Rate limited - try again later" - fi - exit 1 - fi - echo "" - - # Check registry login - echo -e "${BLUE}3. Container Registry Test:${NC}" - runtime=$(just _detect_runtime) - - if echo "$GITHUB_TOKEN" | $runtime login {{REGISTRY}} -u "$GITHUB_USERNAME" --password-stdin >/dev/null 2>&1; then - echo -e "${GREEN} ✓ Registry login successful${NC}" - else - echo -e "${RED} ✗ Registry login failed${NC}" - echo " Check your token permissions" - exit 1 - fi - - echo "" - echo -e "${GREEN}✓ All authentication checks passed!${NC}" - echo -e "${BLUE}You can now use: just push , just pull ${NC}" \ No newline at end of file diff --git a/registry/mod.just b/registry/mod.just new file mode 100644 index 0000000..baa8e2f --- /dev/null +++ b/registry/mod.just @@ -0,0 +1,65 @@ +# Container registry authentication and management + +# Login to container registry +[group('registry')] +login: + #!/usr/bin/env bash + set -euo pipefail + + if [ -z "${GITHUB_USERNAME:-}" ] || [ -z "${GITHUB_TOKEN:-}" ]; then + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} GITHUB_USERNAME and GITHUB_TOKEN environment variables must be set" >&2 + echo "{{YELLOW}}Please set these in your .env file or environment{{NORMAL}}" >&2 + exit 1 + fi + + runtime=$(just _detect_runtime) + registry="${REGISTRY:-ghcr.io}" + + echo -e "{{BLUE}}Logging into registry: $registry{{NORMAL}}" + echo "$GITHUB_TOKEN" | $runtime login "$registry" -u "$GITHUB_USERNAME" --password-stdin + + echo -e "{{GREEN}}✓ Successfully logged into $registry{{NORMAL}}" + +# Logout from container registry +[group('registry')] +logout: + #!/usr/bin/env bash + set -euo pipefail + + runtime=$(just _detect_runtime) + registry="${REGISTRY:-ghcr.io}" + + echo -e "{{BLUE}}Logging out from registry: $registry{{NORMAL}}" + $runtime logout "$registry" + + echo -e "{{GREEN}}✓ Successfully logged out from $registry{{NORMAL}}" + +# Check registry authentication status +[group('registry')] +check: + #!/usr/bin/env bash + set -euo pipefail + + runtime=$(just _detect_runtime) + registry="${REGISTRY:-ghcr.io}" + + echo -e "{{BLUE}}Registry Configuration:{{NORMAL}}" + echo -e "{{YELLOW}}Registry:{{NORMAL}} $registry" + echo -e "{{YELLOW}}Username:{{NORMAL}} ${GITHUB_USERNAME:-'Not set'}" + echo -e "{{YELLOW}}Token:{{NORMAL}} ${GITHUB_TOKEN:+'Set'}${GITHUB_TOKEN:-'Not set'}" + echo "" + + echo -e "{{BLUE}}Testing registry authentication...{{NORMAL}}" + + # Check if we can access the registry + if echo "$GITHUB_TOKEN" | $runtime login "$registry" -u "$GITHUB_USERNAME" --password-stdin >/dev/null 2>&1; then + echo -e "{{GREEN}}✓ Registry authentication successful{{NORMAL}}" + + # Show configured registries + echo -e "{{BLUE}}Configured registries:{{NORMAL}}" + $runtime system info --format "{{{{.RegistryConfig.IndexConfigs}}}}" 2>/dev/null || echo "Registry config not available" + else + echo -e "{{RED}}✗ Registry authentication failed{{NORMAL}}" + echo -e "{{YELLOW}}Please check your GITHUB_USERNAME and GITHUB_TOKEN{{NORMAL}}" + exit 1 + fi \ No newline at end of file diff --git a/volumes.just b/volumes/mod.just similarity index 68% rename from volumes.just rename to volumes/mod.just index f1af093..ddf0ed6 100644 --- a/volumes.just +++ b/volumes/mod.just @@ -3,7 +3,7 @@ # Clean all volumes used by compose file (DESTRUCTIVE!) [group('volumes')] [confirm] -volumes-clean-all compose-file="": +clean-all compose-file="": #!/usr/bin/env bash set -euo pipefail @@ -16,34 +16,34 @@ volumes-clean-all compose-file="": file_arg="-f $compose_file" fi - echo -e "{{RED}}⚠️ WARNING: This will DELETE ALL DATA!{{NC}}" - echo -e "{{YELLOW}}This will remove all volumes defined in the compose file{{NC}}" + echo -e "{{RED}}⚠️ WARNING: This will DELETE ALL DATA!{{NORMAL}}" + echo -e "{{YELLOW}}This will remove all volumes defined in the compose file{{NORMAL}}" # Show which volumes would be removed - echo -e "{{BLUE}}Volumes that will be removed:{{NC}}" + echo -e "{{BLUE}}Volumes that will be removed:{{NORMAL}}" $compose_cmd $file_arg config --volumes 2>/dev/null || echo "Cannot list volumes from compose file" echo "" - echo -e "{{BLUE}}Stopping services...{{NC}}" + echo -e "{{BLUE}}Stopping services...{{NORMAL}}" $compose_cmd $file_arg down - echo -e "{{BLUE}}Removing volumes...{{NC}}" + echo -e "{{BLUE}}Removing volumes...{{NORMAL}}" $compose_cmd $file_arg down -v - echo -e "{{GREEN}}✓ All volumes removed{{NC}}" + echo -e "{{GREEN}}✓ All volumes removed{{NORMAL}}" # Remove specific volume by name (DESTRUCTIVE!) [group('volumes')] [confirm] -volumes-remove volume_name: +remove volume_name: #!/usr/bin/env bash set -euo pipefail volume_name="{{volume_name}}" if [ -z "$volume_name" ]; then - echo "Error: Volume name is required" >&2 - echo "Usage: just volumes-remove my_volume_name" >&2 + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} Volume name is required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just volumes remove my_volume_name" >&2 exit 1 fi @@ -51,30 +51,30 @@ volumes-remove volume_name: # Check if volume exists if ! $runtime volume ls --format "table {{{{.Name}}}}" | grep -q "^${volume_name}$"; then - echo -e "{{YELLOW}}Volume '$volume_name' does not exist{{NC}}" + echo -e "{{YELLOW}}Volume '$volume_name' does not exist{{NORMAL}}" exit 0 fi - echo -e "{{RED}}⚠️ WARNING: This will DELETE VOLUME DATA!{{NC}}" - echo -e "{{YELLOW}}This will remove volume: $volume_name{{NC}}" + echo -e "{{RED}}⚠️ WARNING: This will DELETE VOLUME DATA!{{NORMAL}}" + echo -e "{{YELLOW}}This will remove volume: $volume_name{{NORMAL}}" - echo -e "{{BLUE}}Removing volume: $volume_name{{NC}}" + echo -e "{{BLUE}}Removing volume: $volume_name{{NORMAL}}" $runtime volume rm "$volume_name" 2>/dev/null || true - echo -e "{{GREEN}}✓ Volume '$volume_name' removed{{NC}}" + echo -e "{{GREEN}}✓ Volume '$volume_name' removed{{NORMAL}}" # Remove volumes matching pattern (DESTRUCTIVE!) [group('volumes')] [confirm] -volumes-remove-pattern pattern: +remove-pattern pattern: #!/usr/bin/env bash set -euo pipefail pattern="{{pattern}}" if [ -z "$pattern" ]; then - echo "Error: Volume pattern is required" >&2 - echo "Usage: just volumes-remove-pattern 'myproject_*'" >&2 + echo "{{BOLD}}{{RED}}Error:{{NORMAL}} Volume pattern is required" >&2 + echo "{{YELLOW}}Usage:{{NORMAL}} just volumes remove-pattern 'myproject_*'" >&2 exit 1 fi @@ -84,16 +84,16 @@ volumes-remove-pattern pattern: matching_volumes=$($runtime volume ls --format "table {{{{.Name}}}}" | grep "$pattern" || true) if [ -z "$matching_volumes" ]; then - echo -e "{{YELLOW}}No volumes found matching pattern: $pattern{{NC}}" + echo -e "{{YELLOW}}No volumes found matching pattern: $pattern{{NORMAL}}" exit 0 fi - echo -e "{{RED}}⚠️ WARNING: This will DELETE VOLUME DATA!{{NC}}" - echo -e "{{YELLOW}}Volumes matching pattern '$pattern':{{NC}}" + echo -e "{{RED}}⚠️ WARNING: This will DELETE VOLUME DATA!{{NORMAL}}" + echo -e "{{YELLOW}}Volumes matching pattern '$pattern':{{NORMAL}}" echo "$matching_volumes" echo "" - echo -e "{{BLUE}}Removing matching volumes...{{NC}}" + echo -e "{{BLUE}}Removing matching volumes...{{NORMAL}}" echo "$matching_volumes" | while IFS= read -r volume; do if [ -n "$volume" ]; then echo "Removing: $volume" @@ -101,11 +101,11 @@ volumes-remove-pattern pattern: fi done - echo -e "{{GREEN}}✓ Matching volumes removed{{NC}}" + echo -e "{{GREEN}}✓ Matching volumes removed{{NORMAL}}" # List all volumes or filter by pattern [group('volumes')] -volumes-list pattern="": +list pattern="": #!/usr/bin/env bash set -euo pipefail @@ -113,9 +113,9 @@ volumes-list pattern="": runtime=$(just _detect_runtime) if [ -n "$pattern" ]; then - echo -e "{{BLUE}}Volumes matching pattern '$pattern':{{NC}}" + echo -e "{{BLUE}}Volumes matching pattern '$pattern':{{NORMAL}}" $runtime volume ls | grep "$pattern" || echo "No volumes found matching pattern: $pattern" else - echo -e "{{BLUE}}All volumes:{{NC}}" + echo -e "{{BLUE}}All volumes:{{NORMAL}}" $runtime volume ls fi \ No newline at end of file