diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 65366990..5861c35d 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -28,7 +28,7 @@ jobs: node-version: 22 - name: Install Dependencies - run: npm i -g npminstall && npminstall + run: npm i - name: Lint run: npm run lint @@ -38,6 +38,79 @@ jobs: - name: Build run: npm run tsc && npm run tsc:prod + + test-deployment: + runs-on: ubuntu-latest + + concurrency: + group: test-deployment-${{ github.workflow }}-#${{ github.event.pull_request.number || github.head_ref || github.ref }} + cancel-in-progress: true + + services: + mysql: + image: mysql:5.7 + env: + MYSQL_ALLOW_EMPTY_PASSWORD: true + MYSQL_DATABASE: cnpmcore + ports: + - 3306:3306 + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=5 + redis: + # https://docs.github.com/en/actions/using-containerized-services/about-service-containers#example-mapping-redis-ports + image: redis + ports: + # Opens tcp port 6379 on the host and service container + - 6379:6379 + + steps: + - name: Checkout Git Source + uses: actions/checkout@v5 + + - name: Use Node.js + uses: actions/setup-node@v6 + with: + node-version: 22 + + - name: Install Dependencies + run: npm i + + - name: Test Deployment + run: | + npm run build + echo "Preparing database..." + CNPMCORE_DATABASE_NAME=cnpmcore bash ./prepare-database-mysql.sh + echo "Starting cnpmcore..." + CNPMCORE_FORCE_LOCAL_FS=true npm run start:foreground & + sleep 5 + echo "Checking cnpmcore is ready..." + + set -Eeuo pipefail + URL="http://127.0.0.1:7001" + PATTERN="instance_start_time" + TIMEOUT=60 + TMP="$(mktemp)" + echo "🔎 Health check $URL, expect 200 & body contains: $PATTERN" + deadline=$((SECONDS + TIMEOUT)) + last_status="" + + while (( SECONDS < deadline )); do + last_status="$(curl -sS -o "$TMP" -w '%{http_code}' "$URL" || true)" + echo "last_status=$last_status" + echo "body=$(cat $TMP)" + if [[ "$last_status" == "200" ]] && grep -q "$PATTERN" "$TMP"; then + echo "✅ OK" + rm -f "$TMP" + npx eggctl stop + exit 0 + fi + sleep 1 + done + + echo "::error::❌ Health check failed: status=$last_status" + echo "---- Response body (last try) ----" + cat "$TMP" || true + rm -f "$TMP" + exit 1 test-postgresql-fs-nfs: strategy: @@ -91,7 +164,7 @@ jobs: node-version: ${{ matrix.node-version }} - name: Install Dependencies - run: npm i -g npminstall && npminstall + run: npm i # https://github.com/elastic/elastic-github-actions/blob/master/elasticsearch/README.md - name: Configure sysctl limits @@ -178,7 +251,7 @@ jobs: node-version: ${{ matrix.node-version }} - name: Install Dependencies - run: npm i -g npminstall && npminstall + run: npm i - name: Continuous Integration run: npm run ci diff --git a/app/infra/NFSClientAdapter.ts b/app/infra/NFSClientAdapter.ts index c67d55aa..39d2d3d3 100644 --- a/app/infra/NFSClientAdapter.ts +++ b/app/infra/NFSClientAdapter.ts @@ -43,7 +43,8 @@ export class NFSClientAdapter implements NFSClient { if (this.config.nfs.client) { this._client = this.config.nfs.client; } else { - if (this.config.env === 'prod') { + // Please do not set the CNPMCORE_FORCE_LOCAL_FS environment variable unless you know what you are doing. + if (this.config.env === 'prod' && process.env.CNPMCORE_FORCE_LOCAL_FS !== 'true') { throw new Error( "[NFSAdapter] Can't use local fs NFS on production env" ); diff --git a/package.json b/package.json index 7cb8ab8f..bf83dc9b 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "ci": "npm run cov", "ci:postgresql": "npm run cov:postgresql", "clean": "tsc -b --clean && rm -rf dist *.tsbuildinfo", + "build": "npm run tsc", "tsc": "npm run clean && tsc -p ./tsconfig.json", "tsc:prod": "npm run clean && tsc -p ./tsconfig.prod.json", "prepublishOnly": "npm run tsc:prod",