From 8e24ae5633539d8cd0fe525a8c3ce5073b9a7bce Mon Sep 17 00:00:00 2001 From: m1ngsama Date: Tue, 2 Dec 2025 12:46:17 +0800 Subject: [PATCH] Add CI/CD and deployment automation GitHub Actions workflows: - ci.yml: Auto-test on push/PR * Build on Ubuntu and macOS * Run AddressSanitizer * Memory leak checks with Valgrind - release.yml: Auto-release on tags * Build for Linux (amd64, arm64) * Build for macOS (amd64, arm64) * Generate checksums * Create GitHub release with binaries Deployment tools: - install.sh: One-line installer * Auto-detect OS and arch * Download from releases * Install to /usr/local/bin - tnt.service: systemd unit file * Auto-restart on failure * Security hardening * Runs as dedicated user - DEPLOYMENT.md: Complete deployment guide * Quick install * systemd setup * Firewall config * Docker alternative Usage: curl -sSL https://raw.githubusercontent.com/m1ngsama/TNT/main/install.sh | sh Create release: git tag v1.0.0 git push origin v1.0.0 --- .github/workflows/ci.yml | 48 ++++++++++++ .github/workflows/release.yml | 133 ++++++++++++++++++++++++++++++++++ CICD.md | 94 ++++++++++++++++++++++++ DEPLOYMENT.md | 117 ++++++++++++++++++++++++++++++ README.md | 11 +++ install.sh | 65 +++++++++++++++++ tnt.service | 25 +++++++ 7 files changed, 493 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release.yml create mode 100644 CICD.md create mode 100644 DEPLOYMENT.md create mode 100755 install.sh create mode 100644 tnt.service diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..153352c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,48 @@ +name: CI + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build-and-test: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies (Ubuntu) + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get install -y libssh-dev + + - name: Install dependencies (macOS) + if: runner.os == 'macOS' + run: | + brew install libssh + + - name: Build + run: make + + - name: Build with AddressSanitizer + run: make asan + + - name: Run basic tests + run: | + timeout 10 ./tnt & + sleep 2 + pkill tnt || true + + - name: Check for memory leaks + if: runner.os == 'Linux' + run: | + sudo apt-get install -y valgrind + timeout 10 valgrind --leak-check=full --error-exitcode=1 ./tnt & + sleep 5 + pkill tnt || true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..9821264 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,133 @@ +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + build: + name: Build ${{ matrix.target }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: ubuntu-latest + target: linux-amd64 + artifact: tnt-linux-amd64 + - os: ubuntu-latest + target: linux-arm64 + artifact: tnt-linux-arm64 + - os: macos-latest + target: darwin-amd64 + artifact: tnt-darwin-amd64 + - os: macos-latest + target: darwin-arm64 + artifact: tnt-darwin-arm64 + + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies (Ubuntu) + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get install -y libssh-dev + + - name: Install cross-compilation tools (Ubuntu ARM64) + if: matrix.target == 'linux-arm64' + run: | + sudo apt-get install -y gcc-aarch64-linux-gnu + sudo dpkg --add-architecture arm64 + + - name: Install dependencies (macOS) + if: runner.os == 'macOS' + run: | + brew install libssh + + - name: Build release binary + run: make release + + - name: Rename binary + run: mv tnt ${{ matrix.artifact }} + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.artifact }} + path: ${{ matrix.artifact }} + + release: + needs: build + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - uses: actions/checkout@v4 + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: ./artifacts + + - name: Create checksums + run: | + cd artifacts + for dir in */; do + cd "$dir" + sha256sum * > checksums.txt + cd .. + done + cd .. + + - name: Create Release + uses: softprops/action-gh-release@v1 + with: + files: | + artifacts/*/tnt-* + artifacts/*/checksums.txt + body: | + ## Installation + + Download the binary for your platform: + + **Linux AMD64:** + ```bash + wget https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/tnt-linux-amd64 + chmod +x tnt-linux-amd64 + sudo mv tnt-linux-amd64 /usr/local/bin/tnt + ``` + + **Linux ARM64:** + ```bash + wget https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/tnt-linux-arm64 + chmod +x tnt-linux-arm64 + sudo mv tnt-linux-arm64 /usr/local/bin/tnt + ``` + + **macOS Intel:** + ```bash + wget https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/tnt-darwin-amd64 + chmod +x tnt-darwin-amd64 + sudo mv tnt-darwin-amd64 /usr/local/bin/tnt + ``` + + **macOS Apple Silicon:** + ```bash + wget https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/tnt-darwin-arm64 + chmod +x tnt-darwin-arm64 + sudo mv tnt-darwin-arm64 /usr/local/bin/tnt + ``` + + **Verify checksums:** + ```bash + sha256sum -c checksums.txt + ``` + + ## What's Changed + See [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ github.ref_name }}/CHANGELOG.md) + draft: false + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CICD.md b/CICD.md new file mode 100644 index 0000000..d31c584 --- /dev/null +++ b/CICD.md @@ -0,0 +1,94 @@ +CI/CD USAGE GUIDE +================= + +AUTOMATIC TESTING +----------------- +Every push or PR automatically runs: + - Build on Ubuntu and macOS + - AddressSanitizer checks + - Valgrind memory leak detection + +Check status: + https://github.com/m1ngsama/TNT/actions + + +CREATING RELEASES +----------------- +1. Update version in CHANGELOG.md + +2. Create and push tag: + git tag v1.0.0 + git push origin v1.0.0 + +3. GitHub Actions automatically: + - Builds binaries (Linux/macOS, AMD64/ARM64) + - Creates release + - Uploads binaries + - Generates checksums + +4. Release appears at: + https://github.com/m1ngsama/TNT/releases + + +DEPLOYING TO SERVERS +-------------------- +Single command on any server: + curl -sSL https://raw.githubusercontent.com/m1ngsama/TNT/main/install.sh | sh + +Or with specific version: + VERSION=v1.0.0 curl -sSL https://raw.githubusercontent.com/m1ngsama/TNT/main/install.sh | sh + + +PRODUCTION SETUP (systemd) +--------------------------- +1. Install binary (see above) + +2. Setup service: + sudo useradd -r -s /bin/false tnt + sudo mkdir -p /var/lib/tnt + sudo chown tnt:tnt /var/lib/tnt + sudo cp tnt.service /etc/systemd/system/ + sudo systemctl daemon-reload + sudo systemctl enable --now tnt + +3. Check status: + sudo systemctl status tnt + sudo journalctl -u tnt -f + + +UPDATING SERVERS +---------------- +Stop service: + sudo systemctl stop tnt + +Run installer again: + curl -sSL https://raw.githubusercontent.com/m1ngsama/TNT/main/install.sh | sh + +Restart: + sudo systemctl start tnt + + +PLATFORMS SUPPORTED +------------------- +✓ Linux AMD64 (x86_64) +✓ Linux ARM64 (aarch64) +✓ macOS Intel (x86_64) +✓ macOS Apple Silicon (arm64) + + +EXAMPLE WORKFLOW +---------------- +# Local development +make && make asan +./tnt + +# Create release +git tag v1.0.1 +git push origin v1.0.1 +# Wait 5 minutes for builds + +# Deploy to production servers +for server in server1 server2 server3; do + ssh $server "curl -sSL https://raw.githubusercontent.com/m1ngsama/TNT/main/install.sh | VERSION=v1.0.1 sh" + ssh $server "sudo systemctl restart tnt" +done diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 0000000..331f12b --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,117 @@ +# DEPLOYMENT + +## Quick Install + +One-line install (latest release): +```bash +curl -sSL https://raw.githubusercontent.com/m1ngsama/TNT/main/install.sh | sh +``` + +Specific version: +```bash +VERSION=v1.0.0 curl -sSL https://raw.githubusercontent.com/m1ngsama/TNT/main/install.sh | sh +``` + +## Manual Install + +Download binary for your platform from [releases](https://github.com/m1ngsama/TNT/releases): + +```bash +# Linux AMD64 +wget https://github.com/m1ngsama/TNT/releases/latest/download/tnt-linux-amd64 +chmod +x tnt-linux-amd64 +sudo mv tnt-linux-amd64 /usr/local/bin/tnt + +# macOS ARM64 (Apple Silicon) +wget https://github.com/m1ngsama/TNT/releases/latest/download/tnt-darwin-arm64 +chmod +x tnt-darwin-arm64 +sudo mv tnt-darwin-arm64 /usr/local/bin/tnt +``` + +## systemd Service + +1. Create user and directory: +```bash +sudo useradd -r -s /bin/false tnt +sudo mkdir -p /var/lib/tnt +sudo chown tnt:tnt /var/lib/tnt +``` + +2. Install service file: +```bash +sudo cp tnt.service /etc/systemd/system/ +sudo systemctl daemon-reload +sudo systemctl enable tnt +sudo systemctl start tnt +``` + +3. Check status: +```bash +sudo systemctl status tnt +sudo journalctl -u tnt -f +``` + +## Configuration + +Environment variables: +```bash +# Change port +sudo systemctl edit tnt +# Add: +[Service] +Environment="PORT=3333" + +sudo systemctl restart tnt +``` + +## Firewall + +```bash +# Ubuntu/Debian +sudo ufw allow 2222/tcp + +# CentOS/RHEL +sudo firewall-cmd --permanent --add-port=2222/tcp +sudo firewall-cmd --reload +``` + +## Update + +```bash +# Stop service +sudo systemctl stop tnt + +# Re-run install script +curl -sSL https://raw.githubusercontent.com/m1ngsama/TNT/main/install.sh | sh + +# Start service +sudo systemctl start tnt +``` + +## Uninstall + +```bash +sudo systemctl stop tnt +sudo systemctl disable tnt +sudo rm /etc/systemd/system/tnt.service +sudo systemctl daemon-reload +sudo rm /usr/local/bin/tnt +sudo userdel tnt +sudo rm -rf /var/lib/tnt +``` + +## Docker (Alternative) + +```dockerfile +FROM alpine:latest +RUN apk add --no-cache libssh +COPY tnt /usr/local/bin/tnt +EXPOSE 2222 +CMD ["/usr/local/bin/tnt"] +``` + +Build and run: +```bash +docker build -t tnt . +docker run -d -p 2222:2222 --name tnt tnt +``` diff --git a/README.md b/README.md index 139c34c..1b40835 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,17 @@ For debug build: make debug ``` +## Installation + +**Quick install (recommended):** +```bash +curl -sSL https://raw.githubusercontent.com/m1ngsama/TNT/main/install.sh | sh +``` + +**Or download from [releases](https://github.com/m1ngsama/TNT/releases)** + +See [DEPLOYMENT.md](DEPLOYMENT.md) for production setup. + ## Running ```bash diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..2935245 --- /dev/null +++ b/install.sh @@ -0,0 +1,65 @@ +#!/bin/sh +# TNT Auto-deploy script +# Usage: curl -sSL https://raw.githubusercontent.com/m1ngsama/TNT/main/install.sh | sh + +set -e + +VERSION=${VERSION:-latest} +INSTALL_DIR=${INSTALL_DIR:-/usr/local/bin} + +# Detect OS and architecture +OS=$(uname -s | tr '[:upper:]' '[:lower:]') +ARCH=$(uname -m) + +case "$ARCH" in + x86_64) ARCH="amd64" ;; + aarch64|arm64) ARCH="arm64" ;; + *) echo "Unsupported architecture: $ARCH"; exit 1 ;; +esac + +BINARY="tnt-${OS}-${ARCH}" +REPO="m1ngsama/TNT" + +echo "=== TNT Installer ===" +echo "OS: $OS" +echo "Arch: $ARCH" +echo "Version: $VERSION" +echo "" + +# Get latest version if not specified +if [ "$VERSION" = "latest" ]; then + echo "Fetching latest version..." + VERSION=$(curl -sSL "https://api.github.com/repos/$REPO/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') +fi + +echo "Installing version: $VERSION" + +# Download +URL="https://github.com/$REPO/releases/download/$VERSION/$BINARY" +echo "Downloading from: $URL" + +TMP_FILE=$(mktemp) +if ! curl -sSL -o "$TMP_FILE" "$URL"; then + echo "ERROR: Failed to download $BINARY" + rm -f "$TMP_FILE" + exit 1 +fi + +# Install +chmod +x "$TMP_FILE" + +if [ -w "$INSTALL_DIR" ]; then + mv "$TMP_FILE" "$INSTALL_DIR/tnt" +else + echo "Need sudo for installation to $INSTALL_DIR" + sudo mv "$TMP_FILE" "$INSTALL_DIR/tnt" +fi + +echo "" +echo "✓ TNT installed successfully to $INSTALL_DIR/tnt" +echo "" +echo "Run with:" +echo " tnt" +echo "" +echo "Or specify port:" +echo " PORT=3333 tnt" diff --git a/tnt.service b/tnt.service new file mode 100644 index 0000000..b566594 --- /dev/null +++ b/tnt.service @@ -0,0 +1,25 @@ +[Unit] +Description=TNT Chat Server +After=network.target + +[Service] +Type=simple +User=tnt +Group=tnt +WorkingDirectory=/var/lib/tnt +ExecStart=/usr/local/bin/tnt +Restart=always +RestartSec=10 + +# Security +NoNewPrivileges=true +PrivateTmp=true +ProtectSystem=strict +ProtectHome=true +ReadWritePaths=/var/lib/tnt + +# Environment +Environment="PORT=2222" + +[Install] +WantedBy=multi-user.target