Files
Workflow config file is invalid. Please check your config file: yaml: line 139: could not find expected ':'
你的用户名 dd70b4299a
Some checks failed
CI / build (push) Has been cancelled
Add GitHub Actions deployment workflow
- Add automated deployment workflow configuration
- Configure CI/CD pipeline for bc-netts-energy

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 15:24:38 +08:00

170 lines
5.1 KiB
YAML

name: Deploy
on:
push:
branches: ["main"]
workflow_dispatch:
env:
APP_NAME: bc-netts-energy
BINARY_NAME: netts-energy
jobs:
build-and-deploy:
runs-on: ubuntu-latest
env:
SERVICE_PORT: ${{ secrets.SERVICE_PORT }}
NETTS_API_KEY: ${{ secrets.NETTS_API_KEY }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "1.24"
- name: Go module cache
uses: actions/cache@v4
with:
path: |
~/go/pkg/mod
~/.cache/go-build
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Run unit tests
run: go test ./...
- name: Build binary
run: |
mkdir -p build
go build -o build/${{ env.BINARY_NAME }} ./cmd/server
- name: Upload binary to server
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.SSH_HOST }}
port: ${{ secrets.SSH_PORT }}
username: ${{ secrets.SSH_USER }}
password: ${{ secrets.SSH_PASSWORD }}
source: build/${{ env.BINARY_NAME }}
target: /tmp
- name: Deploy on remote host
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SSH_HOST }}
port: ${{ secrets.SSH_PORT }}
username: ${{ secrets.SSH_USER }}
password: ${{ secrets.SSH_PASSWORD }}
script_stop: true
command_timeout: 30m
envs: APP_NAME,BINARY_NAME,SERVICE_PORT,GITHUB_SHA,NETTS_API_KEY
script: |
set -euo pipefail
APP_DIR="/opt/${APP_NAME}"
RELEASE_ROOT="${APP_DIR}/releases"
RELEASE_PATH="${RELEASE_ROOT}/${GITHUB_SHA}"
CURRENT_LINK="${APP_DIR}/current"
SHARED_DIR="${APP_DIR}/shared"
BINARY_PATH="${RELEASE_PATH}/${BINARY_NAME}"
REMOTE_TMP="/tmp/${BINARY_NAME}"
mkdir -p "${RELEASE_ROOT}" "${SHARED_DIR}"
if [ ! -f "${REMOTE_TMP}" ]; then
echo "Binary ${REMOTE_TMP} not found on remote host." >&2
exit 1
fi
mkdir -p "${RELEASE_PATH}"
mv "${REMOTE_TMP}" "${BINARY_PATH}"
chmod +x "${BINARY_PATH}"
SERVICE_NAME="${APP_NAME}.service"
SERVICE_EXISTS=0
if systemctl list-unit-files "${SERVICE_NAME}" >/dev/null 2>&1; then
SERVICE_EXISTS=1
if systemctl is-active --quiet "${SERVICE_NAME}"; then
systemctl stop "${SERVICE_NAME}"
fi
fi
TARGET_PORT="${SERVICE_PORT:-8080}"
if command -v ss >/dev/null 2>&1; then
LISTEN_CMD="ss -ltn"
elif command -v netstat >/dev/null 2>&1; then
LISTEN_CMD="netstat -ltn"
else
echo "Neither ss nor netstat is available to check port usage." >&2
rm -rf "${RELEASE_PATH}"
if [ "${SERVICE_EXISTS}" = "1" ]; then
systemctl start "${SERVICE_NAME}"
fi
exit 1
fi
if ${LISTEN_CMD} | awk '{print $4}' | grep -q ":${TARGET_PORT}$"; then
echo "Port ${TARGET_PORT} is already in use. Deployment aborted." >&2
rm -rf "${RELEASE_PATH}"
if [ "${SERVICE_EXISTS}" = "1" ]; then
systemctl start "${SERVICE_NAME}"
fi
exit 1
fi
if [ ! -f "${SHARED_DIR}/config.yaml" ]; then
echo "Missing config at ${SHARED_DIR}/config.yaml. Deployment aborted." >&2
rm -rf "${RELEASE_PATH}"
if [ "${SERVICE_EXISTS}" = "1" ]; then
systemctl start "${SERVICE_NAME}"
fi
exit 1
fi
if [ -z "${NETTS_API_KEY:-}" ]; then
echo "NETTS_API_KEY is not provided. Deployment aborted." >&2
rm -rf "${RELEASE_PATH}"
if [ "${SERVICE_EXISTS}" = "1" ]; then
systemctl start "${SERVICE_NAME}"
fi
exit 1
fi
if [ ! -f "/etc/systemd/system/${SERVICE_NAME}" ]; then
cat <<EOF > "/etc/systemd/system/${SERVICE_NAME}"
[Unit]
Description=BC Netts Energy Service
After=network.target
[Service]
Type=simple
WorkingDirectory=${APP_DIR}/current
ExecStart=${APP_DIR}/current/${BINARY_NAME} -config ${SHARED_DIR}/config.yaml
Restart=on-failure
RestartSec=5
EnvironmentFile=-/opt/${APP_NAME}/shared/.env
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable "${SERVICE_NAME}"
else
systemctl daemon-reload
fi
ln -sfn "${RELEASE_PATH}" "${CURRENT_LINK}"
ENV_FILE="${SHARED_DIR}/.env"
cat <<EOF > "${ENV_FILE}"
NETTS_API_KEY=${NETTS_API_KEY}
EOF
chmod 600 "${ENV_FILE}"
systemctl restart "${SERVICE_NAME}"
systemctl --no-pager status "${SERVICE_NAME}"