diff --git a/.github/workflows/offline-package-argocd-installer.yaml b/.github/workflows/offline-package-argocd-installer.yaml index c47a615..c49ddc2 100644 --- a/.github/workflows/offline-package-argocd-installer.yaml +++ b/.github/workflows/offline-package-argocd-installer.yaml @@ -53,14 +53,7 @@ jobs: id: resolve env: OVERRIDE_CHART_VERSION: ${{ github.event.inputs.chart_version }} - run: | - set -euo pipefail - if [ -n "${OVERRIDE_CHART_VERSION}" ]; then - CHART_VERSION="${OVERRIDE_CHART_VERSION}" - else - CHART_VERSION=$(helm search repo argo/argo-cd --versions | awk 'NR==2{print $2}') - fi - echo "chart_version=${CHART_VERSION}" >> "$GITHUB_OUTPUT" + run: bash scripts/offline-argocd/resolve_chart_version.sh - name: Prepare directories run: | @@ -71,45 +64,7 @@ jobs: - name: Stage installer script env: CHART_VERSION: ${{ steps.resolve.outputs.chart_version }} - run: | - set -euo pipefail - cat <<'SCRIPT' > argocd-offline-package/scripts/install-argocd.sh -#!/usr/bin/env bash -set -euo pipefail - -ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -CHART_DIR="${ROOT_DIR}/charts/argo-cd" -IMAGES_DIR="${ROOT_DIR}/images" -RELEASE_NAME="${RELEASE_NAME:-argo-cd}" -NAMESPACE="${NAMESPACE:-argocd}" - -if command -v nerdctl >/dev/null 2>&1; then - LOADER="nerdctl" -elif command -v docker >/dev/null 2>&1; then - LOADER="docker" -else - echo "Either docker or nerdctl is required to load images." >&2 - exit 1 -fi - -for tar in "${IMAGES_DIR}"/*.tar; do - [ -f "$tar" ] || continue - echo "Loading image: $tar" - "$LOADER" load -i "$tar" -done - -echo "Installing/Upgrading Argo CD release ${RELEASE_NAME} in namespace ${NAMESPACE}" -helm upgrade --install "${RELEASE_NAME}" "${CHART_DIR}" \ - --namespace "${NAMESPACE}" \ - --create-namespace \ - "$@" -SCRIPT - chmod +x argocd-offline-package/scripts/install-argocd.sh - cat < argocd-offline-package/metadata/INFO -chart: argo/argo-cd -chart_version: ${CHART_VERSION} -created_at: $(date -u +%Y-%m-%dT%H:%M:%SZ) -EOFMETA + run: bash scripts/offline-argocd/stage_installer.sh - name: Download nerdctl binary for ${{ matrix.arch }} run: | @@ -120,25 +75,8 @@ EOFMETA - name: Pull & export required images env: CHART_VERSION: ${{ steps.resolve.outputs.chart_version }} - run: | - set -euo pipefail - PLATFORM="linux/${{ matrix.arch }}" - helm template argo argo/argo-cd --version "${CHART_VERSION}" > manifest.yaml - mapfile -t images < <(grep -oP 'image:\s*"?\K([^"\s]+)' manifest.yaml | sort -u || true) - rm -f manifest.yaml - for img in "${images[@]}"; do - [ -n "$img" ] || continue - if [[ "$img" == *"{{"* ]]; then - continue - fi - echo "Pulling $img for ${PLATFORM}" - if ! docker pull --platform "${PLATFORM}" "$img"; then - echo "::warning::Failed to pull $img for ${PLATFORM}, skipping" >&2 - continue - fi - safe=$(echo "$img" | tr '/:' '-_') - docker save "$img" -o "argocd-offline-package/images/${safe}.tar" - done + MATRIX_ARCH: ${{ matrix.arch }} + run: bash scripts/offline-argocd/pull_and_export_images.sh - name: Download Helm chart env: @@ -238,15 +176,7 @@ EOFMETA 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/amd64/offline-package-argocd-amd64.tar.gz \ - release-artifacts/arm64/offline-package-argocd-arm64.tar.gz \ - "${RSYNC_SSH_USER}@${VPS_HOST}:${REMOTE_DIR}/" + run: bash scripts/offline-argocd/rsync_release_assets.sh retention: name: Remote retention (keep latest 3) @@ -267,20 +197,4 @@ EOFMETA 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 - mapfile -t all < <(ls -1 | grep -E "^(offline-argocd-|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 - ' + run: bash scripts/offline-argocd/prune_remote_versions.sh diff --git a/.github/workflows/offline-package-fluxcd-installer.yaml b/.github/workflows/offline-package-fluxcd-installer.yaml index 5a96053..6e2c53c 100644 --- a/.github/workflows/offline-package-fluxcd-installer.yaml +++ b/.github/workflows/offline-package-fluxcd-installer.yaml @@ -53,14 +53,7 @@ jobs: id: resolve env: OVERRIDE_CHART_VERSION: ${{ github.event.inputs.chart_version }} - run: | - set -euo pipefail - if [ -n "${OVERRIDE_CHART_VERSION}" ]; then - CHART_VERSION="${OVERRIDE_CHART_VERSION}" - else - CHART_VERSION=$(helm search repo fluxcd-community/flux2 --versions | awk 'NR==2{print $2}') - fi - echo "chart_version=${CHART_VERSION}" >> "$GITHUB_OUTPUT" + run: script/offline-fluxcd/resolve-chart-version.sh - name: Prepare directories run: | @@ -71,45 +64,7 @@ jobs: - name: Stage installer script env: CHART_VERSION: ${{ steps.resolve.outputs.chart_version }} - run: | - set -euo pipefail - cat <<'SCRIPT' > offline-installer/scripts/install-fluxcd.sh -#!/usr/bin/env bash -set -euo pipefail - -ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -CHART_DIR="${ROOT_DIR}/charts/flux2" -IMAGES_DIR="${ROOT_DIR}/images" -RELEASE_NAME="${RELEASE_NAME:-flux-system}" -NAMESPACE="${NAMESPACE:-flux-system}" - -if command -v nerdctl >/dev/null 2>&1; then - LOADER="nerdctl" -elif command -v docker >/dev/null 2>&1; then - LOADER="docker" -else - echo "Either docker or nerdctl is required to load images." >&2 - exit 1 -fi - -for tar in "${IMAGES_DIR}"/*.tar; do - [ -f "$tar" ] || continue - echo "Loading image: $tar" - "$LOADER" load -i "$tar" -done - -echo "Installing/Upgrading FluxCD release ${RELEASE_NAME} in namespace ${NAMESPACE}" -helm upgrade --install "${RELEASE_NAME}" "${CHART_DIR}" \ - --namespace "${NAMESPACE}" \ - --create-namespace \ - "$@" -SCRIPT - chmod +x offline-installer/scripts/install-fluxcd.sh - cat < offline-installer/metadata/INFO -chart: fluxcd-community/flux2 -chart_version: ${CHART_VERSION} -created_at: $(date -u +%Y-%m-%dT%H:%M:%SZ) -EOFMETA + run: script/offline-fluxcd/stage-installer.sh - name: Download nerdctl binary for ${{ matrix.arch }} run: | @@ -120,25 +75,8 @@ EOFMETA - name: Pull & export required images env: CHART_VERSION: ${{ steps.resolve.outputs.chart_version }} - run: | - set -euo pipefail - PLATFORM="linux/${{ matrix.arch }}" - helm template flux fluxcd-community/flux2 --version "${CHART_VERSION}" > manifest.yaml - mapfile -t images < <(grep -oP 'image:\s*"?\K([^"\s]+)' manifest.yaml | sort -u || true) - rm -f manifest.yaml - for img in "${images[@]}"; do - [ -n "$img" ] || continue - if [[ "$img" == *"{{"* ]]; then - continue - fi - echo "Pulling $img for ${PLATFORM}" - if ! docker pull --platform "${PLATFORM}" "$img"; then - echo "::warning::Failed to pull $img for ${PLATFORM}, skipping" >&2 - continue - fi - safe=$(echo "$img" | tr '/:' '-_') - docker save "$img" -o "offline-installer/images/${safe}.tar" - done + MATRIX_ARCH: ${{ matrix.arch }} + run: script/offline-fluxcd/pull-and-export-images.sh - name: Download Helm chart env: diff --git a/.github/workflows/offline-package-gitlab-installer.yaml b/.github/workflows/offline-package-gitlab-installer.yaml index df66c26..60d65e6 100644 --- a/.github/workflows/offline-package-gitlab-installer.yaml +++ b/.github/workflows/offline-package-gitlab-installer.yaml @@ -36,12 +36,7 @@ jobs: - 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 + run: script/install-offline-gitlab-deps.sh - name: Add helm repo run: | @@ -53,14 +48,7 @@ jobs: id: resolve env: OVERRIDE_CHART_VERSION: ${{ github.event.inputs.chart_version }} - run: | - set -euo pipefail - if [ -n "${OVERRIDE_CHART_VERSION}" ]; then - CHART_VERSION="${OVERRIDE_CHART_VERSION}" - else - CHART_VERSION=$(helm search repo gitlab/gitlab --versions | awk 'NR==2{print $2}') - fi - echo "chart_version=${CHART_VERSION}" >> "$GITHUB_OUTPUT" + run: script/resolve-gitlab-chart-version.sh - name: Prepare directories run: | @@ -71,45 +59,7 @@ jobs: - name: Stage installer script env: CHART_VERSION: ${{ steps.resolve.outputs.chart_version }} - run: | - set -euo pipefail - cat <<'SCRIPT' > offline-installer/scripts/install-gitlab.sh -#!/usr/bin/env bash -set -euo pipefail - -ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -CHART_DIR="${ROOT_DIR}/charts/gitlab" -IMAGES_DIR="${ROOT_DIR}/images" -RELEASE_NAME="${RELEASE_NAME:-gitlab}" -NAMESPACE="${NAMESPACE:-gitlab}" - -if command -v nerdctl >/dev/null 2>&1; then - LOADER="nerdctl" -elif command -v docker >/dev/null 2>&1; then - LOADER="docker" -else - echo "Either docker or nerdctl is required to load images." >&2 - exit 1 -fi - -for tar in "${IMAGES_DIR}"/*.tar; do - [ -f "$tar" ] || continue - echo "Loading image: $tar" - "$LOADER" load -i "$tar" -done - -echo "Installing/Upgrading GitLab release ${RELEASE_NAME} in namespace ${NAMESPACE}" -helm upgrade --install "${RELEASE_NAME}" "${CHART_DIR}" \ - --namespace "${NAMESPACE}" \ - --create-namespace \ - "$@" -SCRIPT - chmod +x offline-installer/scripts/install-gitlab.sh - cat < offline-installer/metadata/INFO -chart: gitlab/gitlab -chart_version: ${CHART_VERSION} -created_at: $(date -u +%Y-%m-%dT%H:%M:%SZ) -EOFMETA + run: script/stage-gitlab-offline-installer.sh - name: Download nerdctl binary for ${{ matrix.arch }} run: | @@ -120,25 +70,8 @@ EOFMETA - name: Pull & export required images env: CHART_VERSION: ${{ steps.resolve.outputs.chart_version }} - run: | - set -euo pipefail - PLATFORM="linux/${{ matrix.arch }}" - helm template gitlab gitlab/gitlab --version "${CHART_VERSION}" > manifest.yaml - mapfile -t images < <(grep -oP 'image:\s*"?\K([^"\s]+)' manifest.yaml | sort -u || true) - rm -f manifest.yaml - for img in "${images[@]}"; do - [ -n "$img" ] || continue - if [[ "$img" == *"{{"* ]]; then - continue - fi - echo "Pulling $img for ${PLATFORM}" - if ! docker pull --platform "${PLATFORM}" "$img"; then - echo "::warning::Failed to pull $img for ${PLATFORM}, skipping" >&2 - continue - fi - safe=$(echo "$img" | tr '/:' '-_') - docker save "$img" -o "offline-installer/images/${safe}.tar" - done + ARCH: ${{ matrix.arch }} + run: script/pull-and-export-gitlab-images.sh - name: Download Helm chart env: diff --git a/.github/workflows/offline-package-pulumi-installer.yaml b/.github/workflows/offline-package-pulumi-installer.yaml index 0064d13..d264a84 100644 --- a/.github/workflows/offline-package-pulumi-installer.yaml +++ b/.github/workflows/offline-package-pulumi-installer.yaml @@ -43,73 +43,15 @@ jobs: id: resolve env: OVERRIDE_VERSION: ${{ github.event.inputs.pulumi_version }} - run: | - set -euo pipefail - if [ -n "${OVERRIDE_VERSION}" ]; then - VERSION="${OVERRIDE_VERSION}" - else - VERSION=$(curl -fsSL https://api.github.com/repos/pulumi/pulumi/releases?per_page=100 \ - | jq -r '.[].tag_name' \ - | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \ - | sed 's/^v//' \ - | sort -V \ - | tail -n 1) - fi - if [ -z "${VERSION}" ]; then - echo "Failed to resolve Pulumi version" >&2 - exit 1 - fi - echo "Resolved Pulumi version: ${VERSION}" - echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + run: script/resolve-pulumi-version.sh - name: Build offline Pulumi package env: + ARCH: ${{ matrix.arch }} PULUMI_VERSION: ${{ steps.resolve.outputs.version }} - run: | - set -euo pipefail - ARCH="${{ matrix.arch }}" - case "$ARCH" in - amd64) ASSET_ARCH="x64" ;; - arm64) ASSET_ARCH="arm64" ;; - *) echo "Unsupported arch: $ARCH" >&2; exit 1 ;; - esac - WORKDIR="pulumi-offline-package" - rm -rf "${WORKDIR}" - mkdir -p "${WORKDIR}" "${WORKDIR}/scripts" + MATRIX_ARCH: ${{ matrix.arch }} - ARCHIVE="pulumi-v${PULUMI_VERSION}-linux-${ASSET_ARCH}.tar.gz" - URL="https://get.pulumi.com/releases/sdk/${ARCHIVE}" - echo "Downloading ${URL}" - curl -fSL "${URL}" -o "${ARCHIVE}" - - tar -xzvf "${ARCHIVE}" -C "${WORKDIR}" --strip-components=1 - rm -f "${ARCHIVE}" - - echo "${PULUMI_VERSION}" > "${WORKDIR}/VERSION" - - cat <<'SCRIPT' > "${WORKDIR}/scripts/install-pulumi.sh" -#!/usr/bin/env bash -set -euo pipefail - -ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -BIN_DIR="${ROOT_DIR}/bin" -INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}" - -if [[ "${1:-}" == "--install" ]]; then - sudo install -m 0755 "${BIN_DIR}"/* "${INSTALL_DIR}/" - echo "Pulumi binaries installed to ${INSTALL_DIR}" -else - cat <> ~/.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/amd64/offline-package-pulumi-amd64.tar.gz \ - release-artifacts/arm64/offline-package-pulumi-arm64.tar.gz \ - "${RSYNC_SSH_USER}@${VPS_HOST}:${REMOTE_DIR}/" + run: script/rsync-release-assets.sh retention: name: Remote retention (keep latest 3) @@ -231,6 +161,8 @@ SCRIPT VPS_HOST: ${{ secrets.VPS_HOST }} REMOTE_ROOT: /data/update-server/pulumi steps: + - uses: actions/checkout@v4 + - name: Init SSH run: | set -euo pipefail @@ -240,20 +172,4 @@ SCRIPT 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 - mapfile -t all < <(ls -1 | grep -E "^(offline-pulumi-|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 - ' + run: script/prune-remote-versions.sh diff --git a/script/build-offline-pulumi-package.sh b/script/build-offline-pulumi-package.sh new file mode 100755 index 0000000..3ca0869 --- /dev/null +++ b/script/build-offline-pulumi-package.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +set -euo pipefail + + +ARCH="${MATRIX_ARCH:-}" +if [[ -z "${ARCH}" ]]; then + echo "MATRIX_ARCH environment variable is required" >&2 + +PULUMI_VERSION="${PULUMI_VERSION:?PULUMI_VERSION is required}" +ARCH="${ARCH:-}" + +if [ -z "${ARCH}" ]; then + echo "ARCH environment variable is required" >&2 + exit 1 +fi + +case "${ARCH}" in + amd64) ASSET_ARCH="x64" ;; + arm64) ASSET_ARCH="arm64" ;; + *) + echo "Unsupported arch: ${ARCH}" >&2 + exit 1 + ;; +esac + +WORKDIR="pulumi-offline-package" +rm -rf "${WORKDIR}" +mkdir -p "${WORKDIR}" "${WORKDIR}/scripts" + +ARCHIVE="pulumi-v${PULUMI_VERSION}-linux-${ASSET_ARCH}.tar.gz" +URL="https://get.pulumi.com/releases/sdk/${ARCHIVE}" +echo "Downloading ${URL}" +curl -fSL "${URL}" -o "${ARCHIVE}" + +tar -xzvf "${ARCHIVE}" -C "${WORKDIR}" --strip-components=1 +rm -f "${ARCHIVE}" + +echo "${PULUMI_VERSION}" > "${WORKDIR}/VERSION" + +cat <<'SCRIPT' > "${WORKDIR}/scripts/install-pulumi.sh" +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +BIN_DIR="${ROOT_DIR}/bin" +INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}" + +if [[ "${1:-}" == "--install" ]]; then + sudo install -m 0755 "${BIN_DIR}"/* "${INSTALL_DIR}/" + echo "Pulumi binaries installed to ${INSTALL_DIR}" +else + cat < manifest.yaml +mapfile -t images < <(grep -oP 'image:\s*"?\K([^"\s]+)' manifest.yaml | sort -u || true) +rm -f manifest.yaml + +for img in "${images[@]}"; do + [[ -n "$img" ]] || continue + if [[ "$img" == *"{{"* ]]; then + continue + fi + echo "Pulling $img for ${PLATFORM}" + if ! docker pull --platform "${PLATFORM}" "$img"; then + echo "::warning::Failed to pull $img for ${PLATFORM}, skipping" >&2 + continue + fi + safe=$(echo "$img" | tr '/:' '-_') + docker save "$img" -o "offline-installer/images/${safe}.tar" +done diff --git a/script/offline-fluxcd/resolve-chart-version.sh b/script/offline-fluxcd/resolve-chart-version.sh new file mode 100755 index 0000000..ee9d77c --- /dev/null +++ b/script/offline-fluxcd/resolve-chart-version.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -euo pipefail + +OVERRIDE_CHART_VERSION="${OVERRIDE_CHART_VERSION:-}" # compatibility +if [[ -n "${OVERRIDE_CHART_VERSION}" ]]; then + CHART_VERSION="${OVERRIDE_CHART_VERSION}" +else + CHART_VERSION=$(helm search repo fluxcd-community/flux2 --versions | awk 'NR==2{print $2}') +fi + +echo "chart_version=${CHART_VERSION}" >> "${GITHUB_OUTPUT}" diff --git a/script/offline-fluxcd/stage-installer.sh b/script/offline-fluxcd/stage-installer.sh new file mode 100755 index 0000000..9428662 --- /dev/null +++ b/script/offline-fluxcd/stage-installer.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +set -euo pipefail + +: "${CHART_VERSION?CHART_VERSION is required}" + +rm -f offline-installer/scripts/install-fluxcd.sh +override_dir="offline-installer" +mkdir -p "${override_dir}/scripts" "${override_dir}/metadata" + +cat <<'SCRIPT' > "${override_dir}/scripts/install-fluxcd.sh" +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +CHART_DIR="${ROOT_DIR}/charts/flux2" +IMAGES_DIR="${ROOT_DIR}/images" +RELEASE_NAME="${RELEASE_NAME:-flux-system}" +NAMESPACE="${NAMESPACE:-flux-system}" + +if command -v nerdctl >/dev/null 2>&1; then + LOADER="nerdctl" +elif command -v docker >/dev/null 2>&1; then + LOADER="docker" +else + echo "Either docker or nerdctl is required to load images." >&2 + exit 1 +fi + +for tar in "${IMAGES_DIR}"/*.tar; do + [ -f "$tar" ] || continue + echo "Loading image: $tar" + "$LOADER" load -i "$tar" +done + +echo "Installing/Upgrading FluxCD release ${RELEASE_NAME} in namespace ${NAMESPACE}" +helm upgrade --install "${RELEASE_NAME}" "${CHART_DIR}" \ + --namespace "${NAMESPACE}" \ + --create-namespace \ + "$@" +SCRIPT +chmod +x "${override_dir}/scripts/install-fluxcd.sh" + +cat < "${override_dir}/metadata/INFO" +chart: fluxcd-community/flux2 +chart_version: ${CHART_VERSION} +created_at: $(date -u +%Y-%m-%dT%H:%M:%SZ) +EOF_META diff --git a/script/pull-and-export-gitlab-images.sh b/script/pull-and-export-gitlab-images.sh new file mode 100755 index 0000000..cc0bc8b --- /dev/null +++ b/script/pull-and-export-gitlab-images.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -euo pipefail + +CHART_VERSION="${CHART_VERSION:?CHART_VERSION is required}" +ARCH="${ARCH:?ARCH is required}" +PLATFORM="linux/${ARCH}" + +helm template gitlab gitlab/gitlab --version "${CHART_VERSION}" > manifest.yaml +mapfile -t images < <(grep -oP 'image:\s*"?\K([^"\s]+)' manifest.yaml | sort -u || true) +rm -f manifest.yaml + +for img in "${images[@]}"; do + [ -n "$img" ] || continue + if [[ "$img" == *"{{"* ]]; then + continue + fi + echo "Pulling $img for ${PLATFORM}" + if ! docker pull --platform "${PLATFORM}" "$img"; then + echo "::warning::Failed to pull $img for ${PLATFORM}, skipping" >&2 + continue + fi + safe=$(echo "$img" | tr '/:' '-_') + docker save "$img" -o "offline-installer/images/${safe}.tar" +done diff --git a/script/resolve-gitlab-chart-version.sh b/script/resolve-gitlab-chart-version.sh new file mode 100755 index 0000000..1347ccd --- /dev/null +++ b/script/resolve-gitlab-chart-version.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -euo pipefail + +OVERRIDE_CHART_VERSION="${OVERRIDE_CHART_VERSION:-}" + +if [[ -n "${OVERRIDE_CHART_VERSION}" ]]; then + CHART_VERSION="${OVERRIDE_CHART_VERSION}" +else + CHART_VERSION=$(helm search repo gitlab/gitlab --versions | awk 'NR==2{print $2}') +fi + +echo "chart_version=${CHART_VERSION}" >> "${GITHUB_OUTPUT}" diff --git a/script/resolve-pulumi-version.sh b/script/resolve-pulumi-version.sh new file mode 100755 index 0000000..8b7676d --- /dev/null +++ b/script/resolve-pulumi-version.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [[ -n "${OVERRIDE_VERSION:-}" ]]; then + VERSION="${OVERRIDE_VERSION}" +else + VERSION=$(curl -fsSL https://api.github.com/repos/pulumi/pulumi/releases?per_page=100 \ + | jq -r '.[].tag_name' \ + | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \ + | sed 's/^v//' \ + | sort -V \ + | tail -n 1) +fi + +if [[ -z "${VERSION}" ]]; then + echo "Failed to resolve Pulumi version" >&2 + exit 1 +fi + +echo "Resolved Pulumi version: ${VERSION}" +echo "version=${VERSION}" >> "${GITHUB_OUTPUT}" diff --git a/script/rsync-release-assets.sh b/script/rsync-release-assets.sh index cee499e..c0f8702 100755 --- a/script/rsync-release-assets.sh +++ b/script/rsync-release-assets.sh @@ -1,6 +1,12 @@ #!/usr/bin/env bash set -euo pipefail + +if [[ -z "${REMOTE_ROOT:-}" || -z "${TAG_NAME:-}" || -z "${RSYNC_SSH_USER:-}" || -z "${VPS_HOST:-}" ]]; then + echo "Missing required environment variables" >&2 + exit 1 +fi + 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}/" diff --git a/script/stage-gitlab-offline-installer.sh b/script/stage-gitlab-offline-installer.sh new file mode 100755 index 0000000..c963a1f --- /dev/null +++ b/script/stage-gitlab-offline-installer.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +set -euo pipefail + +CHART_VERSION="${CHART_VERSION:?CHART_VERSION is required}" + +cat <<'SCRIPT' > offline-installer/scripts/install-gitlab.sh +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +CHART_DIR="${ROOT_DIR}/charts/gitlab" +IMAGES_DIR="${ROOT_DIR}/images" +RELEASE_NAME="${RELEASE_NAME:-gitlab}" +NAMESPACE="${NAMESPACE:-gitlab}" + +if command -v nerdctl >/dev/null 2>&1; then + LOADER="nerdctl" +elif command -v docker >/dev/null 2>&1; then + LOADER="docker" +else + echo "Either docker or nerdctl is required to load images." >&2 + exit 1 +fi + +for tar in "${IMAGES_DIR}"/*.tar; do + [ -f "$tar" ] || continue + echo "Loading image: $tar" + "$LOADER" load -i "$tar" +done + +echo "Installing/Upgrading GitLab release ${RELEASE_NAME} in namespace ${NAMESPACE}" +helm upgrade --install "${RELEASE_NAME}" "${CHART_DIR}" \ + --namespace "${NAMESPACE}" \ + --create-namespace \ + "$@" +SCRIPT + +chmod +x offline-installer/scripts/install-gitlab.sh + +cat < offline-installer/metadata/INFO +chart: gitlab/gitlab +chart_version: ${CHART_VERSION} +created_at: $(date -u +%Y-%m-%dT%H:%M:%SZ) +EOFMETA diff --git a/script/verify-pulumi-bundle.sh b/script/verify-pulumi-bundle.sh new file mode 100755 index 0000000..bf70241 --- /dev/null +++ b/script/verify-pulumi-bundle.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +set -euo pipefail + + +ARCH="${MATRIX_ARCH:-}" +if [[ -z "${ARCH}" ]]; then + echo "MATRIX_ARCH environment variable is required" >&2 + exit 1 +fi + +cd test-dir/pulumi-offline-package + +test -f VERSION + + +if [[ "${ARCH}" == "amd64" ]]; then + ./bin/pulumi version + ./bin/pulumi version | grep "v${PULUMI_VERSION}" +else + file ./bin/pulumi | grep -E "ARM|aarch64" +fi diff --git a/scripts/offline-argocd/prune_remote_versions.sh b/scripts/offline-argocd/prune_remote_versions.sh new file mode 100755 index 0000000..6c263bc --- /dev/null +++ b/scripts/offline-argocd/prune_remote_versions.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +set -euo pipefail + +SSH_USER="${RSYNC_SSH_USER:?RSYNC_SSH_USER environment variable is required}" +HOST="${VPS_HOST:?VPS_HOST environment variable is required}" +REMOTE_ROOT="${REMOTE_ROOT:?REMOTE_ROOT environment variable is required}" + +ssh -i ~/.ssh/id_rsa "${SSH_USER}@${HOST}" REMOTE_ROOT="${REMOTE_ROOT}" 'bash -s' <<'EOS' +set -euo pipefail +cd "${REMOTE_ROOT}" || exit 0 +keep=3 +mapfile -t all < <(ls -1 | grep -E "^(offline-argocd-|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 +EOS diff --git a/scripts/offline-argocd/pull_and_export_images.sh b/scripts/offline-argocd/pull_and_export_images.sh new file mode 100755 index 0000000..8da9ef1 --- /dev/null +++ b/scripts/offline-argocd/pull_and_export_images.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -euo pipefail + +CHART_VERSION="${CHART_VERSION:?CHART_VERSION environment variable is required}" +MATRIX_ARCH="${MATRIX_ARCH:?MATRIX_ARCH environment variable is required}" + +PLATFORM="linux/${MATRIX_ARCH}" + +temp_manifest=$(mktemp) +trap 'rm -f "${temp_manifest}"' EXIT + +helm template argo argo/argo-cd --version "${CHART_VERSION}" > "${temp_manifest}" +mapfile -t images < <(grep -oP 'image:\s*"?\K([^"\s]+)' "${temp_manifest}" | sort -u || true) + +for img in "${images[@]}"; do + [ -n "$img" ] || continue + if [[ "$img" == *"{{"* ]]; then + continue + fi + echo "Pulling $img for ${PLATFORM}" + if ! docker pull --platform "${PLATFORM}" "$img"; then + echo "::warning::Failed to pull $img for ${PLATFORM}, skipping" >&2 + continue + fi + safe=$(echo "$img" | tr '/:' '-_') + docker save "$img" -o "argocd-offline-package/images/${safe}.tar" +done diff --git a/scripts/offline-argocd/resolve_chart_version.sh b/scripts/offline-argocd/resolve_chart_version.sh new file mode 100755 index 0000000..08d6722 --- /dev/null +++ b/scripts/offline-argocd/resolve_chart_version.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -euo pipefail + +OVERRIDE_CHART_VERSION="${OVERRIDE_CHART_VERSION:-}" +if [[ -n "${OVERRIDE_CHART_VERSION}" ]]; then + CHART_VERSION="${OVERRIDE_CHART_VERSION}" +else + CHART_VERSION=$(helm search repo argo/argo-cd --versions | awk 'NR==2{print $2}') +fi + +if [[ -z "${GITHUB_OUTPUT:-}" ]]; then + echo "GITHUB_OUTPUT environment variable is not set" >&2 + exit 1 +fi + +echo "chart_version=${CHART_VERSION}" >> "${GITHUB_OUTPUT}" diff --git a/scripts/offline-argocd/rsync_release_assets.sh b/scripts/offline-argocd/rsync_release_assets.sh new file mode 100755 index 0000000..dd1265c --- /dev/null +++ b/scripts/offline-argocd/rsync_release_assets.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -euo pipefail + +REMOTE_DIR="${REMOTE_ROOT:?REMOTE_ROOT environment variable is required}/${TAG_NAME:?TAG_NAME environment variable is required}" +SSH_USER="${RSYNC_SSH_USER:?RSYNC_SSH_USER environment variable is required}" +HOST="${VPS_HOST:?VPS_HOST environment variable is required}" + +ssh -i ~/.ssh/id_rsa "${SSH_USER}@${HOST}" "mkdir -p '${REMOTE_DIR}'" +echo "Rsync -> ${HOST}:${REMOTE_DIR}/" +rsync -av -e "ssh -i ~/.ssh/id_rsa" \ + release-artifacts/amd64/offline-package-argocd-amd64.tar.gz \ + release-artifacts/arm64/offline-package-argocd-arm64.tar.gz \ + "${SSH_USER}@${HOST}:${REMOTE_DIR}/" diff --git a/scripts/offline-argocd/stage_installer.sh b/scripts/offline-argocd/stage_installer.sh new file mode 100755 index 0000000..5e682a1 --- /dev/null +++ b/scripts/offline-argocd/stage_installer.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +set -euo pipefail + +CHART_VERSION="${CHART_VERSION:?CHART_VERSION environment variable is required}" + +cat <<'SCRIPT' > argocd-offline-package/scripts/install-argocd.sh +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +CHART_DIR="${ROOT_DIR}/charts/argo-cd" +IMAGES_DIR="${ROOT_DIR}/images" +RELEASE_NAME="${RELEASE_NAME:-argo-cd}" +NAMESPACE="${NAMESPACE:-argocd}" + +if command -v nerdctl >/dev/null 2>&1; then + LOADER="nerdctl" +elif command -v docker >/dev/null 2>&1; then + LOADER="docker" +else + echo "Either docker or nerdctl is required to load images." >&2 + exit 1 +fi + +for tar in "${IMAGES_DIR}"/*.tar; do + [ -f "$tar" ] || continue + echo "Loading image: $tar" + "$LOADER" load -i "$tar" +done + +echo "Installing/Upgrading Argo CD release ${RELEASE_NAME} in namespace ${NAMESPACE}" +helm upgrade --install "${RELEASE_NAME}" "${CHART_DIR}" \ + --namespace "${NAMESPACE}" \ + --create-namespace \ + "$@" +SCRIPT + +chmod +x argocd-offline-package/scripts/install-argocd.sh + +cat < argocd-offline-package/metadata/INFO +chart: argo/argo-cd +chart_version: ${CHART_VERSION} +created_at: $(date -u +%Y-%m-%dT%H:%M:%SZ) +EOFMETA