Skip to content

Conversation

@ding113
Copy link
Owner

@ding113 ding113 commented Nov 29, 2025

Summary

Closes #240

This PR enhances the one-click deployment script with:

  • CLI argument parsing for non-interactive/CI/CD deployments
  • Optional Caddy reverse proxy for automatic HTTPS

Changes

Phase 1: CLI Arguments Support

  • Added parse_args() function with full argument parsing
  • Supported flags: --admin-token, --port, --branch, --db-password, --app-url, --deploy-dir
  • Added -y/--non-interactive flag for fully automated deployments
  • Environment variable fallbacks (CCH_ADMIN_TOKEN, CCH_PORT, etc.)
  • Added --help and --version commands
  • Modified select_branch() to skip prompts in non-interactive mode

Phase 2: Caddy HTTPS Integration

  • Added --domain/-D parameter to enable Caddy reverse proxy
  • Auto-generates Caddyfile with security headers (HSTS, X-Content-Type-Options, etc.)
  • Supports --email for Let's Encrypt certificate notifications
  • Supports custom SSL certificates via --ssl-cert/--ssl-key
  • Added check_ports() function for port 80/443 availability checking
  • Updated docker-compose.yaml generation to include Caddy service
  • Updated success message to show HTTPS URLs

Usage Examples

# Interactive mode (unchanged behavior)
./deploy.sh

# Non-interactive with auto-generated credentials
./deploy.sh --branch main -y

# Full CI/CD deployment
./deploy.sh --admin-token "my-token" --port 8080 --branch main -y

# Production with Caddy HTTPS
./deploy.sh --domain api.example.com --email admin@example.com --branch main -y

Test Plan

  • Verify --help displays usage information
  • Verify --version displays version
  • Verify non-interactive mode skips prompts
  • Verify Caddy configuration generates correct Caddyfile
  • Verify docker-compose includes Caddy service when domain is set
  • Verify backward compatibility (running without arguments works as before)

🤖 Generated with Claude Code

Add command-line argument parsing for non-interactive/CI/CD deployments:
- Support --admin-token, --port, --branch, --db-password, --app-url options
- Support --deploy-dir for custom deployment directory
- Support -y/--non-interactive for fully automated deployments
- Environment variable fallbacks (CCH_ADMIN_TOKEN, CCH_PORT, etc.)

Add optional Caddy reverse proxy for automatic HTTPS:
- Enable with --domain/-D parameter
- Auto-generates Caddyfile with security headers
- Supports --email for Let's Encrypt notifications
- Supports custom SSL certificates via --ssl-cert/--ssl-key
- Port 80/443 availability checking

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@gemini-code-assist
Copy link

Summary of Changes

Hello @ding113, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly upgrades the one-click deployment script by introducing robust command-line argument parsing, making it suitable for automated environments, and by adding an optional Caddy reverse proxy for seamless, automatic HTTPS configuration. These enhancements streamline the deployment process and improve security.

Highlights

  • CLI Argument Parsing: The deployment script now supports command-line arguments for various configurations, enabling non-interactive and CI/CD deployments. This includes flags for admin token, port, branch, DB password, app URL, deploy directory, and a non-interactive mode flag.
  • Caddy HTTPS Integration: An optional Caddy reverse proxy has been integrated to provide automatic HTTPS for deployments. Users can specify a domain and email for Let's Encrypt certificates, or provide custom SSL certificates. The Caddy setup includes security headers and port availability checks.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request significantly enhances the deployment script by adding command-line argument parsing for non-interactive use and integrating Caddy for automatic HTTPS. The changes are well-structured and improve the script's utility for automated environments. My review identifies a few areas for improvement to increase the script's robustness and portability, specifically regarding argument parsing and compatibility with different shell environments and operating systems.

Comment on lines +123 to +126
-t|--admin-token)
ADMIN_TOKEN="$2"
shift 2
;;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current argument parsing logic is fragile. If an option that requires a value (like --admin-token) is provided without one, or if the value provided is actually another option (e.g., ./deploy.sh -t -y), the script will misbehave. It might consume the next option as a value or fail with a shift error. It's crucial to validate that an argument is provided and that it's not another option.

This same logic should be applied to all other options that expect a value (e.g., -p, -b, --db-password).

Suggested change
-t|--admin-token)
ADMIN_TOKEN="$2"
shift 2
;;
-t|--admin-token)
if [[ -z "$2" || "$2" =~ ^- ]]; then
log_error "Option '$1' requires an argument."
exit 1
fi
ADMIN_TOKEN="$2"
shift 2
;;

Comment on lines +393 to +398
if ss -tuln | grep -q ":${port} "; then
log_warning "Port $port is already in use"
port_in_use=true
fi
elif command -v netstat &> /dev/null; then
if netstat -tuln | grep -q ":${port} "; then

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The grep pattern ":${port} " used to check for open ports is not fully portable. It assumes a space character follows the port number in the output of ss and netstat. While this might be true on some Linux distributions, it can fail on others or on different operating systems like macOS, where the spacing might differ. This could lead to the script failing to detect a port that is already in use.

A more robust solution is to use a regular expression that matches the port followed by any whitespace character or the end of the line.

Suggested change
if ss -tuln | grep -q ":${port} "; then
log_warning "Port $port is already in use"
port_in_use=true
fi
elif command -v netstat &> /dev/null; then
if netstat -tuln | grep -q ":${port} "; then
if ss -tuln | grep -qE ":${port}(\s|$)"; then
log_warning "Port $port is already in use"
port_in_use=true
fi
elif command -v netstat &> /dev/null; then
if netstat -tuln | grep -qE ":${port}(\s|$)"; then

log_warning "Ports 80 and/or 443 are in use. Caddy may not start correctly."
if [[ "$NON_INTERACTIVE" != true ]]; then
read -p "Continue anyway? [y/N]: " confirm
if [[ "${confirm,,}" != "y" ]]; then

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The ${confirm,,} syntax for converting a string to lowercase is a feature of Bash 4.0 and newer. Some common environments, notably the default bash on macOS (which is often version 3.2), do not support this. This will cause a "bad substitution" error and break the script on such systems. For better portability, it's recommended to use a more widely supported command like tr.

Suggested change
if [[ "${confirm,,}" != "y" ]]; then
if [[ "$(echo "$confirm" | tr '[:upper:]' '[:lower:]')" != "y" ]]; then

Copy link
Owner Author

@ding113 ding113 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📋 Code Review Summary

This PR adds valuable CLI argument parsing and Caddy HTTPS support to the deployment script. However, there are several input validation issues that should be addressed to prevent runtime failures and improve security.

🔍 Issues Found

  • Critical (🔴): 0 issues
  • High (🟠): 3 issues
  • Medium (🟡): 2 issues
  • Low (🟢): 0 issues

🎯 Priority Actions

  1. Add port number validation (line ~133) - invalid ports will cause Docker failures
  2. Add SSL certificate file existence checks (line ~192) - missing files cause confusing errors
  3. Add domain format validation (line ~157) - malformed domains break Caddy config
  4. Set restrictive permissions on copied SSL private keys (line ~508)
  5. Add email format validation for Let's Encrypt (line ~161)

💡 General Observations

The implementation pattern is good overall, but input validation is consistently missing across multiple CLI arguments. Consider adding a validation helper function that can be reused.


🤖 Automated review by Claude AI - focused on identifying issues for improvement

;;
-b|--branch)
BRANCH_NAME="$2"
shift 2
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High: Missing port number validation

Why this is a problem: The APP_PORT value from CLI args is used directly without validation. Invalid port values (e.g., negative numbers, non-numeric strings, or privileged ports) could cause Docker to fail at runtime or create security issues.

Suggested fix:

            -p|--port)
                APP_PORT="$2"
                # Validate port number
                if ! [[ "$APP_PORT" =~ ^[0-9]+$ ]] || [ "$APP_PORT" -lt 1 ] || [ "$APP_PORT" -gt 65535 ]; then
                    log_error "Invalid port: $APP_PORT. Must be a number between 1 and 65535"
                    exit 1
                fi
                shift 2
                ;;

case "$BRANCH_NAME" in
main)
IMAGE_TAG="latest"
;;
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High: Missing validation for SSL certificate file existence

Why this is a problem: When custom SSL certificates are provided via --ssl-cert and --ssl-key, the script validates that both are provided together but doesn't check if the files actually exist and are readable. This will cause a confusing error later during cp operations.

Suggested fix:

    # Validate SSL certificate files exist and are readable
    if [[ -n "$CUSTOM_SSL_CERT" ]]; then
        if [[ ! -f "$CUSTOM_SSL_CERT" ]]; then
            log_error "SSL certificate file not found: $CUSTOM_SSL_CERT"
            exit 1
        fi
        if [[ ! -r "$CUSTOM_SSL_CERT" ]]; then
            log_error "SSL certificate file not readable: $CUSTOM_SSL_CERT"
            exit 1
        fi
    fi
    if [[ -n "$CUSTOM_SSL_KEY" ]]; then
        if [[ ! -f "$CUSTOM_SSL_KEY" ]]; then
            log_error "SSL key file not found: $CUSTOM_SSL_KEY"
            exit 1
        fi
        if [[ ! -r "$CUSTOM_SSL_KEY" ]]; then
            log_error "SSL key file not readable: $CUSTOM_SSL_KEY"
            exit 1
        fi
    fi

;;
--email)
CADDY_EMAIL="$2"
shift 2
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium: Missing domain format validation

Why this is a problem: The DOMAIN parameter is used directly in Caddyfile generation and URL construction without validation. Malformed domain names (containing spaces, special characters, or shell metacharacters) could cause unexpected behavior or Caddy configuration errors.

Suggested fix:

            -D|--domain)
                DOMAIN="$2"
                # Basic domain format validation
                if ! [[ "$DOMAIN" =~ ^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$ ]]; then
                    log_error "Invalid domain format: $DOMAIN"
                    exit 1
                fi
                shift 2
                ;;

local app_ports_config
if [[ -n "$DOMAIN" ]]; then
# When using Caddy, don't expose app port externally
app_ports_config=""
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High: SSL private key copied without restrictive permissions

Why this is a problem: The SSL private key is copied to the deployment directory without setting restrictive file permissions. Private keys should have mode 600 (owner read/write only) to prevent unauthorized access.

Suggested fix:

    # Copy custom SSL certificates if provided
    if [[ -n "$CUSTOM_SSL_CERT" ]] && [[ -n "$CUSTOM_SSL_KEY" ]]; then
        mkdir -p "$DEPLOY_DIR/certs"
        cp "$CUSTOM_SSL_CERT" "$DEPLOY_DIR/certs/cert.pem"
        cp "$CUSTOM_SSL_KEY" "$DEPLOY_DIR/certs/key.pem"
        # Set restrictive permissions on private key
        chmod 600 "$DEPLOY_DIR/certs/key.pem"
        chmod 644 "$DEPLOY_DIR/certs/cert.pem"
        log_success "Custom SSL certificates copied"
    fi

;;
--ssl-cert)
CUSTOM_SSL_CERT="$2"
shift 2
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium: Missing email format validation for Let's Encrypt

Why this is a problem: The --email parameter is used for Let's Encrypt certificate notifications but is not validated. An invalid email format could cause Let's Encrypt registration to fail silently or produce confusing error messages.

Suggested fix:

            --email)
                CADDY_EMAIL="$2"
                # Basic email format validation
                if ! [[ "$CADDY_EMAIL" =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$ ]]; then
                    log_error "Invalid email format: $CADDY_EMAIL"
                    exit 1
                fi
                shift 2
                ;;

@ding113 ding113 moved this from Backlog to In progress in Claude Code Hub Roadmap Nov 30, 2025
@ding113 ding113 mentioned this pull request Dec 11, 2025
@ding113 ding113 closed this Dec 11, 2025
@github-project-automation github-project-automation bot moved this from In progress to Done in Claude Code Hub Roadmap Dec 11, 2025
@ding113 ding113 deleted the feat/issue-240-deploy-cli-args branch December 11, 2025 10:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request size/M Medium PR (< 500 lines)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant