pipeline { agent { node { label '构建机1' customWorkspace '/home/nanxunai/goujian/workspace/postgresshare-release' } } options { timestamps() disableConcurrentBuilds() skipDefaultCheckout(true) timeout(time: 240, unit: 'MINUTES') buildDiscarder(logRotator(daysToKeepStr: '30', numToKeepStr: '15')) } environment { PATH = '/home/nanxunai/.local/bin:/usr/local/bin:/usr/bin:/bin' DOTNET = '/home/nanxunai/.local/bin/dotnet' FNPACK_BIN = '/home/nanxunai/.local/bin/fnpack' OPENLIST_CREDENTIALS = 'openlist_key' OPENLIST_BASE_URL = 'https://openlist.nxsir.cn' OPENLIST_REMOTE_DIR = '/yidongpan/构建产物/PostgresShare' NPM_CONFIG_CACHE = "${WORKSPACE}/.ci/npm-cache" NUGET_PACKAGES = "${WORKSPACE}/.ci/nuget-packages" DOTNET_CLI_HOME = "${WORKSPACE}/.ci/dotnet-home" POSTGRES_SERVICE_BUILD_TMPDIR = "${WORKSPACE}/.ci/fnos-build" LIVERECORDER_VERIFY_TMPDIR = "${WORKSPACE}/.ci/fnos-verify" // Keep PostgreSQL's Unix-domain socket below Linux's 107-byte path limit. POSTGRES_SERVICE_SMOKE_TMPDIR = "/tmp/postgresshare-smoke-${BUILD_NUMBER}" } stages { stage('Checkout') { steps { deleteDir() checkout scm } } stage('Metadata And Preflight') { steps { script { env.APP_VERSION = sh(script: "sed -n 's/^version=//p' fnos-postgresql/manifest | head -n 1", returnStdout: true).trim() env.SHORT_SHA = sh(script: 'git rev-parse --short=8 HEAD', returnStdout: true).trim() env.FNOS_VERSION = sh(script: ''' set -euo pipefail base="$APP_VERSION"; major=${base%%.*}; remainder=${base#*.} minor=${remainder%%.*}; patch=${remainder#*.} test "$base" = "$major.$minor.$patch" && test "$BUILD_NUMBER" -lt 100000 printf '%s.%s.%s\n' "$major" "$minor" "$((patch * 100000 + BUILD_NUMBER))" ''', returnStdout: true).trim() env.IMMUTABLE_TAG = "${env.APP_VERSION}-b${env.BUILD_NUMBER}-${env.SHORT_SHA}" env.FPK_BASENAME = "nxsir-postgresql-${env.FNOS_VERSION}-x86_64.fpk" env.FPK_PATH = "${env.WORKSPACE}/artifacts/${env.FPK_BASENAME}" env.MANIFEST_PATH = "${env.WORKSPACE}/artifacts/PostgresShare-${env.IMMUTABLE_TAG}-build-manifest.json" currentBuild.displayName = "#${env.BUILD_NUMBER} ${env.IMMUTABLE_TAG}" currentBuild.description = "fnOS ${env.FNOS_VERSION}" } sh ''' set -euo pipefail test "$(uname -m)" = x86_64 for command_name in git curl python3 npm node sha256sum tar apt-get dpkg-deb; do command -v "$command_name" >/dev/null; done test -x "$DOTNET" && test -x "$FNPACK_BIN" mkdir -p "$NPM_CONFIG_CACHE" "$NUGET_PACKAGES" "$DOTNET_CLI_HOME" \ "$POSTGRES_SERVICE_BUILD_TMPDIR" "$LIVERECORDER_VERIFY_TMPDIR" "$POSTGRES_SERVICE_SMOKE_TMPDIR" artifacts available_kb=$(df -Pk "$WORKSPACE" | awk 'NR == 2 { print $4 }') test "$available_kb" -ge 4194304 ''' } } stage('Restore And Test') { steps { sh ''' set -euo pipefail npm ci --prefix frontend npm run build:postgres-admin --prefix frontend "$DOTNET" restore tests/PostgresService.Tests/PostgresService.Tests.csproj --disable-parallel "$DOTNET" test tests/PostgresService.Tests/PostgresService.Tests.csproj -c Release --no-restore \ --logger 'console;verbosity=normal' /maxcpucount:1 ''' } } stage('Build Verify And Smoke fnOS x64') { steps { sh ''' set -euo pipefail PACKAGE_VERSION="$FNOS_VERSION" FNPACK="$FNPACK_BIN" DOTNET="$DOTNET" \ ./scripts/build-postgresql-fnos-package.sh "$FPK_PATH" ./scripts/verify-fnos-package.sh "$FPK_PATH" "$FNOS_VERSION" ./scripts/smoke-postgresql-fnos-package.sh "$FPK_PATH" "$POSTGRES_SERVICE_SMOKE_TMPDIR" fpk_sha=$(awk '{print $1}' "$FPK_PATH.sha256"); export fpk_sha python3 - <<'PY' import json, os, pathlib, subprocess path = pathlib.Path(os.environ['MANIFEST_PATH']) payload = { 'project':'PostgresShare','buildNumber':os.environ['BUILD_NUMBER'], 'commit':subprocess.check_output(['git','rev-parse','HEAD'],text=True).strip(), 'productVersion':os.environ['APP_VERSION'],'fnosVersion':os.environ['FNOS_VERSION'], 'fpk':pathlib.Path(os.environ['FPK_PATH']).name,'fpkSha256':os.environ['fpk_sha'], 'runtime':'PostgreSQL 15 + pgvector 0.8.6' } path.write_text(json.dumps(payload,ensure_ascii=False,indent=2)+chr(10),encoding='utf-8') PY sha256sum "$MANIFEST_PATH" >"$MANIFEST_PATH.sha256" ''' } } stage('Upload Artifacts') { steps { withCredentials([usernamePassword(credentialsId: "${OPENLIST_CREDENTIALS}", usernameVariable: 'OPENLIST_USERNAME', passwordVariable: 'OPENLIST_PASSWORD')]) { sh ''' set -euo pipefail for artifact in "$FPK_PATH" "$FPK_PATH.sha256" "$MANIFEST_PATH" "$MANIFEST_PATH.sha256"; do ./scripts/upload-openlist-artifact.sh "$artifact" "$OPENLIST_REMOTE_DIR" done ''' } } } } post { success { archiveArtifacts artifacts: 'artifacts/*.fpk,artifacts/*.sha256,artifacts/*.json', fingerprint: true } always { sh 'rm -rf -- "$POSTGRES_SERVICE_SMOKE_TMPDIR"' cleanWs(deleteDirs: true, notFailBuild: true) } } }