🚀 MAJOR: Full migration to Just modules with modern features

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.
This commit is contained in:
sHa
2025-09-27 02:27:53 +03:00
parent c359858ee9
commit d3fec4b85a
11 changed files with 928 additions and 775 deletions

388
README.md
View File

@@ -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 <service> [compose-file] # Open shell in container
just container exec <service> <cmd> [compose-file] # Execute command
```
### 🗄️ Database Modules
#### PostgreSQL Module (`postgres`)
```bash
just postgres sql <query> [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 <name> [service] # Create database
just postgres drop-database <name> [service] # Drop database (with confirmation)
just postgres shell [service] [compose-file] # Interactive shell
just postgres restore <backup> [service] [compose-file] # Restore from backup (with confirmation)
```
#### MySQL Module (`mysql`)
```bash
just mysql sql <query> [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 <name> [service] # Create database
just mysql drop-database <name> [service] # Drop database (with confirmation)
just mysql create-user <username> <password> [service] # Create user
just mysql grant-privileges <database> <username> [service] # Grant privileges
just mysql shell [service] [compose-file] # Interactive shell
just mysql restore <backup> <database> [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 <volume-name> # Remove specific volume (with confirmation)
just volumes remove-pattern <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 <project> [tag] # Build project image
just images push <project> [tag] # Push image to registry
just images pull <project> [tag] # Pull image from registry
just images tag <project> <new-tag> # Tag existing image
just images info <project> [tag] # Show image information
just images clean <project> # 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.

View File

@@ -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"

View File

@@ -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 <project> # Build any project image"
echo " just start <service> # Start any service"
echo " just registry-login # Login to registry"
echo " just images build <project> # Build any project image"
echo " just container start <service> # 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/"

View File

@@ -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}}"

294
images/mod.just Normal file
View File

@@ -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}}"

106
justfile Normal file
View File

@@ -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 <service> [compose-file]{{NORMAL}} - Open shell in container"
echo " {{YELLOW}}exec <service> <cmd> [compose-file]{{NORMAL}} - Execute command"
;;
"postgres")
echo "{{BOLD}}{{CYAN}}PostgreSQL Module Commands:{{NORMAL}}"
echo " {{YELLOW}}sql <query> [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 <name> [service]{{NORMAL}} - Create database"
echo " {{YELLOW}}drop-database <name> [service]{{NORMAL}} - Drop database (with confirmation)"
echo " {{YELLOW}}shell [service] [compose-file]{{NORMAL}} - Interactive shell"
echo " {{YELLOW}}restore <backup> [service] [compose-file]{{NORMAL}} - Restore from backup"
;;
"mysql")
echo "{{BOLD}}{{CYAN}}MySQL Module Commands:{{NORMAL}}"
echo " {{YELLOW}}sql <query> [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 <name> [service]{{NORMAL}} - Create database"
echo " {{YELLOW}}drop-database <name> [service]{{NORMAL}} - Drop database (with confirmation)"
echo " {{YELLOW}}create-user <user> <pass> [service]{{NORMAL}} - Create user"
echo " {{YELLOW}}grant-privileges <db> <user> [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 <volume-name>{{NORMAL}} - Remove specific volume (with confirmation)"
echo " {{YELLOW}}remove-pattern <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 <project> [tag]{{NORMAL}} - Build project image"
echo " {{YELLOW}}push <project> [tag]{{NORMAL}} - Push image to registry"
echo " {{YELLOW}}pull <project> [tag]{{NORMAL}} - Pull image from registry"
echo " {{YELLOW}}tag <project> <new-tag>{{NORMAL}} - Tag existing image"
echo " {{YELLOW}}info <project> [tag]{{NORMAL}} - Show image information"
echo " {{YELLOW}}clean <project>{{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

View File

@@ -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}}"
echo -e "{{GREEN}}✓ Database '$database' restored successfully from $backup_file{{NORMAL}}"

View File

@@ -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}}"
echo -e "{{GREEN}}✓ Database restored successfully from $backup_file{{NORMAL}}"

View File

@@ -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 <project>, just pull <project>${NC}"

65
registry/mod.just Normal file
View File

@@ -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

View File

@@ -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