290 lines
10 KiB
YAML
290 lines
10 KiB
YAML
name: Build Offline Nginx Ingress Installer
|
||
|
||
on:
|
||
push:
|
||
paths:
|
||
- 'scripts/ingress-installer.sh'
|
||
- 'scripts/resolve_nginx_ingress_versions.sh'
|
||
- '.github/workflows/offline-package-nginx-ingress.yaml'
|
||
workflow_dispatch:
|
||
inputs:
|
||
tag:
|
||
description: "Release tag to use/sync (e.g., v0.133.0). Leave empty to use offline-nginx-ingress-<run_number>"
|
||
required: false
|
||
type: string
|
||
image_tag:
|
||
description: "Override image tag for nginx/nginx-ingress (e.g., 5.1.1). Leave empty to auto-resolve"
|
||
required: false
|
||
type: string
|
||
chart_version:
|
||
description: "Override helm chart version for nginx-stable/nginx-ingress (e.g., 1.2.3). Leave empty to auto-resolve"
|
||
required: false
|
||
type: string
|
||
major_whitelist:
|
||
description: "Allowed major versions for image tag (regex alternation). Default: 5 (i.e., ^5\\.)"
|
||
required: false
|
||
type: string
|
||
default: "5"
|
||
|
||
permissions:
|
||
contents: write # 需要创建/上传 Release 资产
|
||
|
||
concurrency:
|
||
group: build-offline-nginx-ingress
|
||
cancel-in-progress: false
|
||
|
||
jobs:
|
||
build-offline-installer:
|
||
strategy:
|
||
matrix:
|
||
arch: [amd64, arm64]
|
||
runs-on: ubuntu-latest
|
||
outputs:
|
||
image_tag: ${{ steps.resolve.outputs.image_tag }}
|
||
chart_version: ${{ steps.resolve.outputs.chart_version }}
|
||
artifact-name: ${{ steps.upload-artifact.outputs.artifact-name }}
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Install deps (curl, jq, helm)
|
||
run: |
|
||
set -euo pipefail
|
||
sudo apt-get update -y
|
||
sudo apt-get install -y curl jq
|
||
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
|
||
helm version
|
||
|
||
- name: Add helm repo
|
||
run: |
|
||
set -euo pipefail
|
||
helm repo add nginx-stable https://helm.nginx.com/stable
|
||
helm repo update
|
||
|
||
- name: Resolve latest versions
|
||
id: resolve
|
||
env:
|
||
OVERRIDE_IMAGE_TAG: ${{ github.event.inputs.image_tag }}
|
||
OVERRIDE_CHART_VERSION: ${{ github.event.inputs.chart_version }}
|
||
MAJOR_WHITELIST: ${{ github.event.inputs.major_whitelist }}
|
||
run: |
|
||
set -euo pipefail
|
||
bash scripts/resolve_nginx_ingress_versions.sh
|
||
|
||
- name: Prepare directories
|
||
run: |
|
||
set -euo pipefail
|
||
mkdir -p offline-installer/{images,charts,scripts,bin}
|
||
|
||
# 复制并“盖章”版本号到安装脚本
|
||
- name: Stage installer script and stamp resolved image tag
|
||
env:
|
||
IMG_TAG: ${{ steps.resolve.outputs.image_tag }}
|
||
run: |
|
||
set -euo pipefail
|
||
cp scripts/ingress-installer.sh offline-installer/scripts/
|
||
# 替换默认的 NGINX_IC_IMAGE 与 OCI_NGINX_REF 中的 2.4.0 为解析到的 ${IMG_TAG}
|
||
sed -i -E "s|(NGINX_IC_IMAGE:=nginx/nginx-ingress:)[0-9]+\.[0-9]+\.[0-9]+|\1${IMG_TAG}|" offline-installer/scripts/ingress-installer.sh
|
||
sed -i -E "s|(OCI_NGINX_REF:=nginx-ingress-)[0-9]+\.[0-9]+\.[0-9]+|\1${IMG_TAG}|" offline-installer/scripts/ingress-installer.sh
|
||
chmod +x offline-installer/scripts/ingress-installer.sh
|
||
|
||
- name: Download nerdctl binary for ${{ matrix.arch }}
|
||
run: |
|
||
set -euo pipefail
|
||
wget https://github.com/containerd/nerdctl/releases/download/v2.0.3/nerdctl-2.0.3-linux-${{ matrix.arch }}.tar.gz \
|
||
-O offline-installer/nerdctl.tar.gz
|
||
|
||
- name: Pull & export required images (nginx/nginx-ingress:${{ steps.resolve.outputs.image_tag }})
|
||
env:
|
||
IMG_TAG: ${{ steps.resolve.outputs.image_tag }}
|
||
run: |
|
||
set -euo pipefail
|
||
docker pull "nginx/nginx-ingress:${IMG_TAG}"
|
||
docker pull "registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230407"
|
||
|
||
docker save "nginx/nginx-ingress:${IMG_TAG}" \
|
||
-o offline-installer/images/nginx-ingress.tar
|
||
|
||
docker save "registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230407" \
|
||
-o offline-installer/images/kube-webhook-certgen.tar
|
||
|
||
- name: Download Helm Chart (nginx-stable/nginx-ingress ${{ steps.resolve.outputs.chart_version }})
|
||
env:
|
||
CHART_VERSION: ${{ steps.resolve.outputs.chart_version }}
|
||
run: |
|
||
set -euo pipefail
|
||
helm pull nginx-stable/nginx-ingress --version="${CHART_VERSION}" --untar --untardir offline-installer/charts
|
||
|
||
- name: Package offline installer
|
||
run: |
|
||
set -euo pipefail
|
||
cd offline-installer
|
||
tar czvf ../offline-setup-nginx-ingress-${{ matrix.arch }}.tar.gz ./
|
||
cd ..
|
||
|
||
- name: Upload artifact
|
||
id: upload-artifact
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: offline-setup-nginx-ingress-${{ matrix.arch }}
|
||
path: offline-setup-nginx-ingress-${{ matrix.arch }}.tar.gz
|
||
|
||
test-offline-installer:
|
||
needs: build-offline-installer
|
||
strategy:
|
||
matrix:
|
||
arch: [amd64]
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Download offline installer artifact for ${{ matrix.arch }}
|
||
uses: actions/download-artifact@v4
|
||
with:
|
||
name: offline-setup-nginx-ingress-${{ matrix.arch }}
|
||
path: offline-test
|
||
|
||
- name: Setup K3s and KUBECONFIG for user
|
||
run: |
|
||
set -euo pipefail
|
||
curl -sfL https://get.k3s.io | sudo sh -
|
||
mkdir -p $HOME/.kube
|
||
sudo cp /etc/rancher/k3s/k3s.yaml $HOME/.kube/config
|
||
sudo chown $USER:$USER $HOME/.kube/config
|
||
sudo mkdir -p /root/.kube
|
||
sudo cp /etc/rancher/k3s/k3s.yaml /root/.kube/config
|
||
kubectl get nodes
|
||
kubectl version --client=true
|
||
|
||
- name: Install Helm
|
||
run: |
|
||
set -euo pipefail
|
||
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
|
||
|
||
- name: Load offline installer package
|
||
run: |
|
||
set -euo pipefail
|
||
cd offline-test
|
||
tar -xzvf offline-setup-nginx-ingress-${{ matrix.arch }}.tar.gz
|
||
sudo tar xzvf nerdctl.tar.gz -C /usr/local/bin/
|
||
docker load -i images/nginx-ingress.tar
|
||
docker load -i images/kube-webhook-certgen.tar
|
||
cd ..
|
||
|
||
- name: Run offline installer in K3S cluster
|
||
run: |
|
||
set -euo pipefail
|
||
cd offline-test
|
||
sudo bash scripts/ingress-installer.sh
|
||
sleep 10
|
||
sudo helm list -A
|
||
sudo kubectl -n ingress get pods
|
||
|
||
publish-release:
|
||
needs: test-offline-installer
|
||
runs-on: ubuntu-latest
|
||
env:
|
||
TAG_NAME: ${{ github.event.inputs.tag != '' && github.event.inputs.tag || format('offline-nginx-ingress-{0}', github.run_number) }}
|
||
RSYNC_SSH_KEY: ${{ secrets.RSYNC_SSH_KEY }}
|
||
RSYNC_SSH_USER: ${{ secrets.RSYNC_SSH_USER }}
|
||
VPS_HOST: ${{ secrets.VPS_HOST }}
|
||
REMOTE_ROOT: /data/update-server/nginx-ingress
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Create Release
|
||
id: create_release
|
||
uses: actions/create-release@v1
|
||
with:
|
||
tag_name: ${{ env.TAG_NAME }}
|
||
release_name: Build ${{ env.TAG_NAME }}
|
||
draft: false
|
||
prerelease: false
|
||
env:
|
||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||
|
||
- name: Download amd64 artifact
|
||
uses: actions/download-artifact@v4
|
||
with:
|
||
name: offline-setup-nginx-ingress-amd64
|
||
path: release-artifacts
|
||
|
||
- name: Download arm64 artifact
|
||
uses: actions/download-artifact@v4
|
||
with:
|
||
name: offline-setup-nginx-ingress-arm64
|
||
path: release-artifacts
|
||
|
||
- name: Upload offline installers to GitHub Release
|
||
uses: softprops/action-gh-release@v1
|
||
with:
|
||
tag_name: ${{ env.TAG_NAME }}
|
||
files: |
|
||
release-artifacts/offline-setup-nginx-ingress-amd64.tar.gz
|
||
release-artifacts/offline-setup-nginx-ingress-arm64.tar.gz
|
||
env:
|
||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||
|
||
# === Rsync 到远端 ===
|
||
- name: Ensure deps (rsync, ssh)
|
||
run: |
|
||
set -euo pipefail
|
||
sudo apt-get update -y
|
||
sudo apt-get install -y rsync openssh-client
|
||
|
||
- name: Init SSH
|
||
run: |
|
||
set -euo pipefail
|
||
mkdir -p ~/.ssh
|
||
echo "$RSYNC_SSH_KEY" > ~/.ssh/id_rsa
|
||
chmod 600 ~/.ssh/id_rsa
|
||
ssh-keyscan -H "$VPS_HOST" >> ~/.ssh/known_hosts
|
||
|
||
- name: Rsync release assets to remote
|
||
run: |
|
||
set -euo pipefail
|
||
REMOTE_DIR="${REMOTE_ROOT}/${TAG_NAME}"
|
||
ssh -i ~/.ssh/id_rsa "${RSYNC_SSH_USER}@${VPS_HOST}" "mkdir -p '${REMOTE_DIR}'"
|
||
echo "Rsync -> ${VPS_HOST}:${REMOTE_DIR}/"
|
||
rsync -av -e "ssh -i ~/.ssh/id_rsa" \
|
||
release-artifacts/offline-setup-nginx-ingress-amd64.tar.gz \
|
||
release-artifacts/offline-setup-nginx-ingress-arm64.tar.gz \
|
||
"${RSYNC_SSH_USER}@${VPS_HOST}:${REMOTE_DIR}/"
|
||
|
||
retention:
|
||
name: Remote retention (keep latest 3)
|
||
needs: publish-release
|
||
runs-on: ubuntu-latest
|
||
env:
|
||
RSYNC_SSH_KEY: ${{ secrets.RSYNC_SSH_KEY }}
|
||
RSYNC_SSH_USER: ${{ secrets.RSYNC_SSH_USER }}
|
||
VPS_HOST: ${{ secrets.VPS_HOST }}
|
||
REMOTE_ROOT: /data/update-server/nginx-ingress
|
||
steps:
|
||
- name: Init SSH
|
||
run: |
|
||
set -euo pipefail
|
||
mkdir -p ~/.ssh
|
||
echo "$RSYNC_SSH_KEY" > ~/.ssh/id_rsa
|
||
chmod 600 ~/.ssh/id_rsa
|
||
ssh-keyscan -H "$VPS_HOST" >> ~/.ssh/known_hosts
|
||
|
||
- name: Prune old versions on remote (keep 3)
|
||
run: |
|
||
set -euo pipefail
|
||
ssh -i ~/.ssh/id_rsa "${RSYNC_SSH_USER}@${VPS_HOST}" bash -lc '
|
||
set -euo pipefail
|
||
cd "'"${REMOTE_ROOT}"'" || exit 0
|
||
keep=3
|
||
# 同时兼容两类目录命名:offline-nginx-ingress-* 和 v<semver>
|
||
mapfile -t all < <(ls -1 | grep -E "^(offline-nginx-ingress-|v[0-9]+\.)" | sort -V -r || true)
|
||
if [ "${#all[@]}" -le "$keep" ]; then
|
||
echo "Nothing to prune. Count=${#all[@]}"
|
||
exit 0
|
||
fi
|
||
to_delete=("${all[@]:keep}")
|
||
echo "Pruning old versions: ${to_delete[*]}"
|
||
for d in "${to_delete[@]}"; do
|
||
rm -rf -- "$d"
|
||
done
|
||
'
|