code_packager 0.1.0

A tool to package source code files into a single text file with syntax formatting
Documentation
# =============================================
# 多阶段构建:本地开发 + 生产构建
# =============================================

# 基础构建参数
ARG USE_CHINA_MIRROR=false
ARG ALPINE_MIRROR=mirrors.aliyun.com
ARG RUST_MIRROR=ustc



# =============================================
# 阶段1: 本地开发环境
# =============================================
FROM rust:1.90-alpine3.20 AS development

# 继承构建参数
ARG USE_CHINA_MIRROR
ARG ALPINE_MIRROR
ARG RUST_MIRROR



# 条件性配置 Alpine 镜像源
RUN if [ "$USE_CHINA_MIRROR" = "true" ]; then \
        echo "🔧 Using China Alpine mirror: $ALPINE_MIRROR" && \
        sed -i "s|dl-cdn.alpinelinux.org|$ALPINE_MIRROR|g" /etc/apk/repositories; \
    else \
        echo "🌍 Using default Alpine sources"; \
    fi

# 安装开发工具和依赖
RUN apk update && apk add --no-cache \
    git \
    gcc \
    musl-dev \
    openssl-dev \
    build-base \
    pkgconfig \
    openssl-libs-static \
    bash \
    curl \
    vim \
    htop \
    file

WORKDIR /app

# 复制项目文件
COPY Cargo.toml ./

# 条件性配置 Cargo 国内源 - 修正 heredoc 语法
RUN if [ "$USE_CHINA_MIRROR" = "true" ]; then \
        echo "🔧 Configuring Cargo China mirror: $RUST_MIRROR" && \
        mkdir -p /usr/local/cargo && \
        case "$RUST_MIRROR" in \
            "tuna") \
                echo '[source.crates-io]' > /usr/local/cargo/config.toml && \
                echo 'replace-with = "tuna"' >> /usr/local/cargo/config.toml && \
                echo '' >> /usr/local/cargo/config.toml && \
                echo '[source.tuna]' >> /usr/local/cargo/config.toml && \
                echo 'registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git"' >> /usr/local/cargo/config.toml && \
                echo '' >> /usr/local/cargo/config.toml && \
                echo '[net]' >> /usr/local/cargo/config.toml && \
                echo 'git-fetch-with-cli = true' >> /usr/local/cargo/config.toml \
                ;; \
            "ustc") \
                echo '[source.crates-io]' > /usr/local/cargo/config.toml && \
                echo 'replace-with = "ustc"' >> /usr/local/cargo/config.toml && \
                echo '' >> /usr/local/cargo/config.toml && \
                echo '[source.ustc]' >> /usr/local/cargo/config.toml && \
                echo 'registry = "https://mirrors.ustc.edu.cn/crates.io-index/"' >> /usr/local/cargo/config.toml && \
                echo '' >> /usr/local/cargo/config.toml && \
                echo '[net]' >> /usr/local/cargo/config.toml && \
                echo 'git-fetch-with-cli = true' >> /usr/local/cargo/config.toml \
                ;; \
        esac && \
        echo "✅ Cargo mirror configured: $RUST_MIRROR"; \
    else \
        echo "🌍 Using default Cargo sources"; \
        mkdir -p /usr/local/cargo && \
        echo '[net]' > /usr/local/cargo/config.toml && \
        echo 'git-fetch-with-cli = true' >> /usr/local/cargo/config.toml; \
    fi

# 安装开发工具
RUN cargo install cargo-watch cargo-edit

# 预下载依赖
RUN cargo fetch

# 复制源代码
COPY src/ src/

# 开发环境配置
ENV RUST_LOG=debug
ENV RUST_BACKTRACE=1

# 开发环境默认命令
CMD ["cargo", "watch", "-x", "run", "-x", "test"]

# =============================================
# 阶段2: 构建阶段
# =============================================
FROM rust:1.90-alpine3.20 AS builder

# 继承构建参数
ARG USE_CHINA_MIRROR
ARG ALPINE_MIRROR
ARG RUST_MIRROR



# 条件性配置 Alpine 镜像源
RUN if [ "$USE_CHINA_MIRROR" = "true" ]; then \
        echo "🔧 Using China Alpine mirror: $ALPINE_MIRROR" && \
        sed -i "s|dl-cdn.alpinelinux.org|$ALPINE_MIRROR|g" /etc/apk/repositories; \
    else \
        echo "🌍 Using default Alpine sources"; \
    fi

# 安装构建依赖
RUN apk update && apk add --no-cache \
    git \
    gcc \
    musl-dev \
    openssl-dev \
    build-base \
    pkgconfig \
    openssl-libs-static \
    upx \
    file

WORKDIR /app

# 只复制必要的配置
COPY Cargo.toml ./

# 条件性配置 Cargo 国内源 - 修正 heredoc 语法
RUN if [ "$USE_CHINA_MIRROR" = "true" ]; then \
        echo "🔧 Configuring Cargo China mirror: $RUST_MIRROR" && \
        mkdir -p /usr/local/cargo && \
        case "$RUST_MIRROR" in \
            "tuna") \
                echo '[source.crates-io]' > /usr/local/cargo/config.toml && \
                echo 'replace-with = "tuna"' >> /usr/local/cargo/config.toml && \
                echo '' >> /usr/local/cargo/config.toml && \
                echo '[source.tuna]' >> /usr/local/cargo/config.toml && \
                echo 'registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git"' >> /usr/local/cargo/config.toml && \
                echo '' >> /usr/local/cargo/config.toml && \
                echo '[net]' >> /usr/local/cargo/config.toml && \
                echo 'git-fetch-with-cli = true' >> /usr/local/cargo/config.toml \
                ;; \
            "ustc") \
                echo '[source.crates-io]' > /usr/local/cargo/config.toml && \
                echo 'replace-with = "ustc"' >> /usr/local/cargo/config.toml && \
                echo '' >> /usr/local/cargo/config.toml && \
                echo '[source.ustc]' >> /usr/local/cargo/config.toml && \
                echo 'registry = "https://mirrors.ustc.edu.cn/crates.io-index/"' >> /usr/local/cargo/config.toml && \
                echo '' >> /usr/local/cargo/config.toml && \
                echo '[net]' >> /usr/local/cargo/config.toml && \
                echo 'git-fetch-with-cli = true' >> /usr/local/cargo/config.toml \
                ;; \
        esac && \
        echo "✅ Cargo mirror configured: $RUST_MIRROR"; \
    else \
        echo "🌍 Using default Cargo sources"; \
        mkdir -p /usr/local/cargo && \
        echo '[net]' > /usr/local/cargo/config.toml && \
        echo 'git-fetch-with-cli = true' >> /usr/local/cargo/config.toml; \
    fi

# 创建假的 src 目录来缓存依赖
RUN mkdir -p src && \
    echo "fn main() {}" > src/main.rs && \
    echo "// dummy lib" > src/lib.rs

# 构建依赖(缓存层)
RUN cargo fetch && \
    cargo build --release --target x86_64-unknown-linux-musl

# 现在复制真正的源代码
COPY src/ src/

# 真实构建 - 修正缓存清理
RUN rm -f target/x86_64-unknown-linux-musl/release/deps/code_packager* && \
    touch src/main.rs src/lib.rs && \
    cargo build --release --target x86_64-unknown-linux-musl

# 优化二进制(移除调试符号并压缩)
RUN strip target/x86_64-unknown-linux-musl/release/code_packager && \
    upx --best --lzma target/x86_64-unknown-linux-musl/release/code_packager

# 验证构建结果
RUN echo "=== Build Verification ===" && \
    ls -lh target/x86_64-unknown-linux-musl/release/code_packager && \
    file target/x86_64-unknown-linux-musl/release/code_packager && \
    echo "=== Static Link Check ===" && \
    ldd target/x86_64-unknown-linux-musl/release/code_packager 2>&1 | head -3

# =============================================
# 阶段3: 证书准备阶段
# =============================================
FROM alpine:3.20 AS certs

# 继承构建参数
ARG USE_CHINA_MIRROR
ARG ALPINE_MIRROR

# 条件性配置镜像源
RUN if [ "$USE_CHINA_MIRROR" = "true" ]; then \
        echo "🔧 Using China mirror in certs stage: $ALPINE_MIRROR" && \
        sed -i "s|dl-cdn.alpinelinux.org|$ALPINE_MIRROR|g" /etc/apk/repositories; \
    fi

# 安装证书和时区数据
RUN apk update && apk add --no-cache ca-certificates tzdata && \
    update-ca-certificates

# =============================================
# 阶段5: 最终运行镜像(scratch)
# =============================================
FROM alpine:3.20 AS runtime-alpine

# 继承构建参数
ARG USE_CHINA_MIRROR
ARG ALPINE_MIRROR
ARG RUST_MIRROR



# 复制 SSL 证书(必须,因为你的应用需要 HTTPS)
# COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

# 时区信息
# COPY --from=certs /usr/share/zoneinfo /usr/share/zoneinfo
# ENV TZ=Asia/Shanghai

# 复制二进制文件
WORKDIR /app
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/code_packager /app/code_packager

# 健康检查
# HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
#     CMD [ "/app/code_packager", "--version" ] || exit 1

# 设置入口点
ENTRYPOINT ["/app/code_packager"]

FROM scratch AS runtime

# 继承构建参数
ARG USE_CHINA_MIRROR
ARG ALPINE_MIRROR
ARG RUST_MIRROR



# 复制 SSL 证书(必须,因为你的应用需要 HTTPS)
# COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

# 时区信息
# COPY --from=certs /usr/share/zoneinfo /usr/share/zoneinfo
# ENV TZ=Asia/Shanghai

# 复制二进制文件
WORKDIR /app
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/code_packager /app/code_packager

# 健康检查
# HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
#     CMD [ "/app/code_packager", "--version" ] || exit 1

# 设置入口点
ENTRYPOINT ["/app/code_packager"]