commit 30acfc658a73c8917eebf282fbb1d0bf6f847c77 Author: sHa Date: Fri Sep 26 21:14:43 2025 +0300 Initial commit: Add universal Just recipes - container.just: Universal container operations (start, stop, logs, shell, exec, status) - registry.just: GitHub Container Registry authentication - images.just: Universal image build/push/pull operations - README.md: Documentation and usage instructions These recipes work universally across any project with containerfiles. diff --git a/README.md b/README.md new file mode 100644 index 0000000..9879187 --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +# Just Commons + +Universal Just command recipes for container management across projects. + +## Overview + +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 + +## Usage + +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/container.just' +import 'just-commons/registry.just' +import 'just-commons/images.just' + +# Your project-specific commands +import 'just/postgres.just' +import 'just/servapp.just' +``` + +## Files + +- `container.just` - Universal container operations (start, stop, logs, shell, exec, status) +- `registry.just` - GitHub Container Registry authentication +- `images.just` - Universal image build/push/pull operations + +## Requirements + +- Just command runner +- Docker or Podman +- Git + +## Projects Using This + +- [servass](https://github.com/shadoll/servass) - Universal container image management +- [servass_sh](https://github.com/shadoll/servass_sh) - Production deployment (SH) +- [servass_ri](https://github.com/shadoll/servass_ri) - Production deployment (RI) \ No newline at end of file diff --git a/container.just b/container.just new file mode 100644 index 0000000..86d7bd1 --- /dev/null +++ b/container.just @@ -0,0 +1,321 @@ +# Additional helper commands for service management + +# Environment detection +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" + echo "================================================" + echo "" + + # 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}" + docker_available=true + else + echo -e "${YELLOW}⚠ Docker is installed but daemon is not running${NC}" + docker_available=false + fi + else + echo -e "${RED}✗ Docker not found${NC}" + docker_available=false + fi + + # Check Podman + if command -v podman >/dev/null 2>&1; then + echo -e "${GREEN}✓ Podman detected${NC}" + podman_available=true + else + echo -e "${RED}✗ Podman not found${NC}" + podman_available=false + fi + + echo "" + echo "================================================" + echo " SUMMARY" + echo "================================================" + + if [ "$docker_available" = true ] || [ "$podman_available" = true ]; then + echo -e "${GREEN}🎉 Container runtime available!${NC}" + echo "" + echo "You can use these commands:" + echo " just build postgres # Build PostgreSQL image" + echo " just build servapp # Build ServApp image" + echo " just login # Login to registry" + else + echo -e "${RED}❌ No container runtime available${NC}" + echo "" + echo "Please install Docker or Podman:" + echo " • Docker: https://docs.docker.com/get-docker/" + echo " • Podman: https://podman.io/getting-started/installation" + fi + +# Start service (helper command) +start service: + #!/usr/bin/env bash + set -euo pipefail + + # Colors + GREEN='\033[0;32m' + BLUE='\033[0;34m' + NC='\033[0m' + + service="{{service}}" + runtime=$(just _detect_runtime) + + if [ ! -d "$service" ]; then + echo "Error: Service directory '$service' not found" >&2 + exit 1 + fi + + echo -e "${BLUE}Starting $service service...${NC}" + cd "$service" + + # Detect compose command based on available and working container runtime + if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then + # Docker daemon is running, check for compose + if docker compose version >/dev/null 2>&1; then + docker compose up -d + elif command -v docker-compose >/dev/null 2>&1; then + docker-compose up -d + else + echo "Error: Docker is running but no compose tool found" >&2 + exit 1 + fi + elif command -v podman >/dev/null 2>&1 && command -v podman-compose >/dev/null 2>&1; then + podman-compose up -d + else + echo "Error: No working container runtime with compose tool found" >&2 + exit 1 + fi + + echo -e "${GREEN}✓ $service service started${NC}" + +# Stop service (helper command) +stop service: + #!/usr/bin/env bash + set -euo pipefail + + # Colors + GREEN='\033[0;32m' + BLUE='\033[0;34m' + NC='\033[0m' + + service="{{service}}" + + if [ ! -d "$service" ]; then + echo "Error: Service directory '$service' not found" >&2 + exit 1 + fi + + echo -e "${BLUE}Stopping $service service...${NC}" + cd "$service" + + # Detect compose command based on available and working container runtime + if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then + # Docker daemon is running, check for compose + if docker compose version >/dev/null 2>&1; then + docker compose down + elif command -v docker-compose >/dev/null 2>&1; then + docker-compose down + else + echo "Error: Docker is running but no compose tool found" >&2 + exit 1 + fi + elif command -v podman >/dev/null 2>&1 && command -v podman-compose >/dev/null 2>&1; then + podman-compose down + else + echo "Error: No working container runtime with compose tool found" >&2 + exit 1 + fi + + echo -e "${GREEN}✓ $service service stopped${NC}" + +# Show service logs (helper command) +logs service: + #!/usr/bin/env bash + set -euo pipefail + + service="{{service}}" + + if [ ! -d "$service" ]; then + echo "Error: Service directory '$service' not found" >&2 + exit 1 + fi + + cd "$service" + + # Detect compose command based on available and working container runtime + if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then + # Docker daemon is running, check for compose + if docker compose version >/dev/null 2>&1; then + docker compose logs -f + elif command -v docker-compose >/dev/null 2>&1; then + docker-compose logs -f + else + echo "Error: Docker is running but no compose tool found" >&2 + exit 1 + fi + elif command -v podman >/dev/null 2>&1 && command -v podman-compose >/dev/null 2>&1; then + podman-compose logs -f + else + echo "Error: No working container runtime with compose tool found" >&2 + exit 1 + fi + +# Open shell in running container (helper command) +shell service: + #!/usr/bin/env bash + set -euo pipefail + + # Colors + RED='\033[0;31m' + NC='\033[0m' + + service="{{service}}" + runtime=$(just _detect_runtime) + + # Get first running container for this service + container_id=$($runtime ps -q --filter "label=com.docker.compose.project=$service" | head -n1) + if [ -n "$container_id" ]; then + $runtime exec -it "$container_id" /bin/bash || \ + $runtime exec -it "$container_id" /bin/sh + else + echo -e "${RED}No running containers found for $service${NC}" + echo "Start the service first with: just start $service" + exit 1 + fi + +# Execute command in service container (helper command) +exec service cmd: + #!/usr/bin/env bash + set -euo pipefail + + # Colors + RED='\033[0;31m' + NC='\033[0m' + + service="{{service}}" + command="{{cmd}}" + runtime=$(just _detect_runtime) + + if [ -z "$command" ]; then + echo -e "${RED}No command specified${NC}" >&2 + echo "Usage: just exec $service \"command to execute\"" >&2 + exit 1 + fi + + # Get first running container for this service + container_id=$($runtime ps -q --filter "label=com.docker.compose.project=$service" | head -n1) + if [ -n "$container_id" ]; then + $runtime exec -it "$container_id" sh -c "$command" + else + echo -e "${RED}No running containers found for $service${NC}" + echo "Start the service first with: just start $service" + exit 1 + fi + +# Show service status (helper command) +status service: + #!/usr/bin/env bash + set -euo pipefail + + service="{{service}}" + + if [ ! -d "$service" ]; then + echo "Error: Service directory '$service' not found" >&2 + exit 1 + fi + + cd "$service" + + # Detect compose command based on available and working container runtime + if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then + # Docker daemon is running, check for compose + if docker compose version >/dev/null 2>&1; then + docker compose ps + elif command -v docker-compose >/dev/null 2>&1; then + docker-compose ps + else + echo "Error: Docker is running but no compose tool found" >&2 + exit 1 + fi + elif command -v podman >/dev/null 2>&1 && command -v podman-compose >/dev/null 2>&1; then + podman-compose ps + else + echo "Error: No working container runtime with compose tool found" >&2 + exit 1 + fi + + +# Quick development setup +dev-setup: + #!/usr/bin/env bash + set -euo pipefail + + # Colors + GREEN='\033[0;32m' + BLUE='\033[0;34m' + YELLOW='\033[1;33m' + NC='\033[0m' + + echo -e "${BLUE}Setting up development environment...${NC}" + + # Check environment + just env-check + + echo "" + echo -e "${BLUE}Building development images...${NC}" + + # Build development images + just postgres-dev + just servapp-dev + + echo "" + echo -e "${GREEN}✓ Development environment ready!${NC}" + echo "" + echo -e "${YELLOW}Available commands:${NC}" + echo " just start postgres # Start PostgreSQL service" + echo " just start servapp # Start ServApp service" + echo " just logs postgres # View PostgreSQL logs" + echo " just shell postgres # Connect to PostgreSQL container" + +# Clean all development artifacts +dev-clean: + #!/usr/bin/env bash + set -euo pipefail + + # Colors + GREEN='\033[0;32m' + BLUE='\033[0;34m' + YELLOW='\033[1;33m' + NC='\033[0m' + + echo -e "${BLUE}Cleaning development environment...${NC}" + + runtime=$(just _detect_runtime) + + # Stop any running services + echo -e "${YELLOW}Stopping services...${NC}" + just stop postgres 2>/dev/null || true + just stop servapp 2>/dev/null || true + + # Clean images + echo -e "${YELLOW}Cleaning development images...${NC}" + just clean postgres 2>/dev/null || true + just clean servapp 2>/dev/null || true + + # Remove dev tags + $runtime rmi postgres:dev servapp:dev 2>/dev/null || true + + echo -e "${GREEN}✓ Development environment cleaned${NC}" \ No newline at end of file diff --git a/images.just b/images.just new file mode 100644 index 0000000..8a96d32 --- /dev/null +++ b/images.just @@ -0,0 +1,383 @@ +# Universal image operations - works for any project + +# Detect container runtime +_detect_runtime: + #!/usr/bin/env bash + if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then + echo "docker" + elif command -v podman >/dev/null 2>&1; then + echo "podman" + else + echo "Error: No container runtime available (docker or podman)" >&2 + exit 1 + fi + +# Build any project's container 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 +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 +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 +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 +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 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 +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 build $project $tag" + fi + +# List all project 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 +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 +build-all: + @echo "{{BLUE}}Building all known projects...{{NC}}" + @just build postgres + @just build servapp + @echo "{{GREEN}}✓ All projects built successfully{{NC}}" + +# Quick push all known projects +push-all tag=DEFAULT_TAG: + @echo "{{BLUE}}Pushing all known projects with tag: {{tag}}{{NC}}" + @just push postgres {{tag}} + @just push servapp {{tag}} + @echo "{{GREEN}}✓ All projects pushed successfully{{NC}}" \ No newline at end of file diff --git a/registry.just b/registry.just new file mode 100644 index 0000000..71045f5 --- /dev/null +++ b/registry.just @@ -0,0 +1,172 @@ +# Registry operations + +# Login to container 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 +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 +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