diff --git a/.circleci/config.yml b/.circleci/config.yml index 702181cb0fe..b98bc4b4dfe 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -211,10 +211,10 @@ workflows: config-path: ../workspace/.circleci/continue_config.yml mapping: | comms/.* run-discovery-workflow true - packages/identity-service/.* run-identity-workflow true + packages/identity-service/.* run-identity-workflow false eth-contracts/.* run-eth-contracts-workflow true .circleci/.* run-discovery-workflow true - .circleci/.* run-identity-workflow true + .circleci/.* run-identity-workflow false .circleci/.* run-eth-contracts-workflow true .circleci/.* run-protocol-dashboard-workflow true .circleci/.* run-sdk-workflow true @@ -247,7 +247,7 @@ workflows: packages/fixed-decimal/.* run-mobile-workflow false packages/fixed-decimal/.* run-common-workflow true packages/spl/.* run-sdk-workflow true - packages/spl/.* run-identity-workflow true + packages/spl/.* run-identity-workflow false requires: - generate-config - init @@ -262,10 +262,10 @@ workflows: config-path: ../workspace/.circleci/continue_config.yml mapping: | comms/.* run-discovery-workflow true - packages/identity-service/.* run-identity-workflow true + packages/identity-service/.* run-identity-workflow false eth-contracts/.* run-eth-contracts-workflow true .circleci/.* run-discovery-workflow true - .circleci/.* run-identity-workflow true + .circleci/.* run-identity-workflow false .circleci/.* run-eth-contracts-workflow true .circleci/.* run-protocol-dashboard-workflow true .circleci/.* run-sdk-workflow true @@ -294,7 +294,7 @@ workflows: packages/fixed-decimal/.* run-mobile-workflow false packages/fixed-decimal/.* run-common-workflow true packages/spl/.* run-sdk-workflow true - packages/spl/.* run-identity-workflow true + packages/spl/.* run-identity-workflow false .* run-web-workflow false .* run-mobile-workflow false requires: diff --git a/.circleci/src/workflows/identity.yml b/.circleci/src/workflows/identity.yml index 40dcf276903..62e1bc15c07 100644 --- a/.circleci/src/workflows/identity.yml +++ b/.circleci/src/workflows/identity.yml @@ -1,3 +1,6 @@ +# NOTE: Identity Service CI/CD has been migrated to GitHub Actions +# (.github/workflows/identity.yml). This workflow is disabled via path +# filtering in config.yml (run-identity-workflow is forced to false). when: << pipeline.parameters.run-identity-workflow >> jobs: - identity-init: diff --git a/.github/workflows/identity.yml b/.github/workflows/identity.yml new file mode 100644 index 00000000000..015d280071e --- /dev/null +++ b/.github/workflows/identity.yml @@ -0,0 +1,382 @@ +name: Identity Service CI/CD + +on: + push: + branches: + - main + paths: + - 'packages/identity-service/**' + - 'packages/sdk/**' + - 'packages/spl/**' + - 'packages/eth/**' + - 'packages/fixed-decimal/**' + - 'packages/libs/**' + - 'package-lock.json' + - '.github/workflows/identity.yml' + pull_request: + paths: + - 'packages/identity-service/**' + - 'packages/sdk/**' + - 'packages/spl/**' + - 'packages/eth/**' + - 'packages/fixed-decimal/**' + - 'packages/libs/**' + - 'package-lock.json' + - '.github/workflows/identity.yml' + workflow_dispatch: + +env: + NODE_VERSION: '24.10.0' + +jobs: + identity-init: + name: Identity Init (Install & Cache) + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + cache-dependency-path: package-lock.json + + - name: Upgrade npm to 11.10.0 + run: npm install -g npm@11.10.0 + + - name: Create concatenated patch file + id: patch-file + run: | + ls -d -- packages/*/patches/*.patch 2>/dev/null | xargs cat > combined-patch-file.txt || touch combined-patch-file.txt + echo "patch_checksum=$(sha256sum combined-patch-file.txt | cut -d' ' -f1)" >> $GITHUB_OUTPUT + + - name: Cache node modules + id: cache-node-modules + uses: actions/cache@v4 + with: + path: | + node_modules + packages/identity-service/node_modules + packages/libs/node_modules + packages/libs/dist + packages/sdk/node_modules + packages/sdk/dist + packages/spl/node_modules + packages/spl/dist + packages/eth/node_modules + packages/eth/dist + packages/fixed-decimal/node_modules + packages/fixed-decimal/dist + key: npm-cache-identity-${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }}-${{ steps.patch-file.outputs.patch_checksum }} + restore-keys: | + npm-cache-identity-${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }}- + + - name: Install dependencies + env: + CI: true + SKIP_POD_INSTALL: true + SKIP_ANDROID_INSTALL: true + ANDROID_HOME: /tmp/android-sdk-dummy + NODE_OPTIONS: --max-old-space-size=8192 + run: | + mkdir -p /tmp/android-sdk-dummy + if [[ -d node_modules ]]; then + echo "Using cached node_modules, running postinstall..." + npm run postinstall + else + echo "No cache found, running fresh install..." + npm cache clean --force || true + npm ci --prefer-offline || npm install --prefer-offline + fi + + identity-lint: + name: Identity Lint + runs-on: ubuntu-latest + needs: identity-init + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + cache-dependency-path: package-lock.json + + - name: Upgrade npm to 11.10.0 + run: npm install -g npm@11.10.0 + + - name: Create concatenated patch file + id: patch-file + run: | + ls -d -- packages/*/patches/*.patch 2>/dev/null | xargs cat > combined-patch-file.txt || touch combined-patch-file.txt + echo "patch_checksum=$(sha256sum combined-patch-file.txt | cut -d' ' -f1)" >> $GITHUB_OUTPUT + + - name: Cache node modules + id: cache-node-modules + uses: actions/cache@v4 + with: + path: | + node_modules + packages/identity-service/node_modules + packages/libs/node_modules + packages/libs/dist + packages/sdk/node_modules + packages/sdk/dist + packages/spl/node_modules + packages/spl/dist + packages/eth/node_modules + packages/eth/dist + packages/fixed-decimal/node_modules + packages/fixed-decimal/dist + key: npm-cache-identity-${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }}-${{ steps.patch-file.outputs.patch_checksum }} + restore-keys: | + npm-cache-identity-${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }}- + + - name: Install dependencies (if cache miss) + if: steps.cache-node-modules.outputs.cache-hit != 'true' + env: + CI: true + SKIP_POD_INSTALL: true + SKIP_ANDROID_INSTALL: true + ANDROID_HOME: /tmp/android-sdk-dummy + NODE_OPTIONS: --max-old-space-size=8192 + run: | + mkdir -p /tmp/android-sdk-dummy + npm cache clean --force || true + npm ci --prefer-offline || npm install --prefer-offline + + - name: Cache for Turbo + uses: rharkor/caching-for-turbo@v2.2.1 + + - name: Lint + run: npx turbo run lint --filter=identity-service + + identity-typecheck: + name: Identity Typecheck + runs-on: ubuntu-latest + needs: identity-init + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + cache-dependency-path: package-lock.json + + - name: Upgrade npm to 11.10.0 + run: npm install -g npm@11.10.0 + + - name: Create concatenated patch file + id: patch-file + run: | + ls -d -- packages/*/patches/*.patch 2>/dev/null | xargs cat > combined-patch-file.txt || touch combined-patch-file.txt + echo "patch_checksum=$(sha256sum combined-patch-file.txt | cut -d' ' -f1)" >> $GITHUB_OUTPUT + + - name: Cache node modules + id: cache-node-modules + uses: actions/cache@v4 + with: + path: | + node_modules + packages/identity-service/node_modules + packages/libs/node_modules + packages/libs/dist + packages/sdk/node_modules + packages/sdk/dist + packages/spl/node_modules + packages/spl/dist + packages/eth/node_modules + packages/eth/dist + packages/fixed-decimal/node_modules + packages/fixed-decimal/dist + key: npm-cache-identity-${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }}-${{ steps.patch-file.outputs.patch_checksum }} + restore-keys: | + npm-cache-identity-${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }}- + + - name: Install dependencies (if cache miss) + if: steps.cache-node-modules.outputs.cache-hit != 'true' + env: + CI: true + SKIP_POD_INSTALL: true + SKIP_ANDROID_INSTALL: true + ANDROID_HOME: /tmp/android-sdk-dummy + NODE_OPTIONS: --max-old-space-size=8192 + run: | + mkdir -p /tmp/android-sdk-dummy + npm cache clean --force || true + npm ci --prefer-offline || npm install --prefer-offline + + - name: Cache for Turbo + uses: rharkor/caching-for-turbo@v2.2.1 + + - name: Typecheck + run: npx turbo run typecheck --filter=identity-service + + identity-test: + name: Identity Tests + runs-on: ubuntu-latest + needs: identity-init + services: + postgres: + image: postgres:11.1 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: audius_identity_service_test + ports: + - 7433:5432 + options: >- + --health-cmd pg_isready + --health-interval 5s + --health-timeout 5s + --health-retries 10 + redis: + image: redis:7.0 + ports: + - 6379:6379 + options: >- + --health-cmd "redis-cli ping" + --health-interval 5s + --health-timeout 5s + --health-retries 10 + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + cache-dependency-path: package-lock.json + + - name: Upgrade npm to 11.10.0 + run: npm install -g npm@11.10.0 + + - name: Create concatenated patch file + id: patch-file + run: | + ls -d -- packages/*/patches/*.patch 2>/dev/null | xargs cat > combined-patch-file.txt || touch combined-patch-file.txt + echo "patch_checksum=$(sha256sum combined-patch-file.txt | cut -d' ' -f1)" >> $GITHUB_OUTPUT + + - name: Cache node modules + id: cache-node-modules + uses: actions/cache@v4 + with: + path: | + node_modules + packages/identity-service/node_modules + packages/libs/node_modules + packages/libs/dist + packages/sdk/node_modules + packages/sdk/dist + packages/spl/node_modules + packages/spl/dist + packages/eth/node_modules + packages/eth/dist + packages/fixed-decimal/node_modules + packages/fixed-decimal/dist + key: npm-cache-identity-${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }}-${{ steps.patch-file.outputs.patch_checksum }} + restore-keys: | + npm-cache-identity-${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }}- + + - name: Install dependencies (if cache miss) + if: steps.cache-node-modules.outputs.cache-hit != 'true' + env: + CI: true + SKIP_POD_INSTALL: true + SKIP_ANDROID_INSTALL: true + ANDROID_HOME: /tmp/android-sdk-dummy + NODE_OPTIONS: --max-old-space-size=8192 + run: | + mkdir -p /tmp/android-sdk-dummy + npm cache clean --force || true + npm ci --prefer-offline || npm install --prefer-offline + + - name: Cache for Turbo + uses: rharkor/caching-for-turbo@v2.2.1 + + - name: Build dependencies + run: npx turbo run build --filter=identity-service^... + + # Mirror what CircleCI ran: `npx mocha` with no args (the + # docker-compose.test.yml `test-identity-service` entrypoint shifted "test" + # off and invoked `npx mocha`). Mocha's default `test/*.{js,cjs,mjs}` glob + # picks up only the `.js` test files; `test/index.ts` (which transitively + # imports the solana relay tree and requires populated solana env vars) is + # intentionally skipped, matching prior CI behavior. + - name: Run tests + timeout-minutes: 20 + working-directory: packages/identity-service + env: + isTestRun: 'true' + environment: 'test' + logLevel: 'debug' + redisHost: 'localhost' + redisPort: '6379' + POSTGRES_TEST_PORT: '7433' + dbUrl: 'postgres://postgres:postgres@localhost:7433/audius_identity_service_test' + ethTokenAddress: '' + ethRegistryAddress: '' + registryAddress: '' + ethOwnerWallet: '' + # Bumped from the .mocharc.js default of 12s — each test's beforeEach + # re-runs all migrations from scratch, which is slow on ubuntu-latest + # compared to the CircleCI xlarge machine the original timeout targeted. + run: npx mocha --timeout 60000 + + identity-docker-push: + name: Push identity-service Docker image + runs-on: ubuntu-latest + needs: [identity-lint, identity-typecheck, identity-test] + if: github.ref == 'refs/heads/main' && github.event_name == 'push' + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push identity-service image + uses: docker/build-push-action@v6 + with: + context: . + file: packages/identity-service/Dockerfile.prod + push: true + tags: audius/identity-service:${{ github.sha }} + build-args: | + git_sha=${{ github.sha }} + cache-from: type=gha,scope=identity-service + cache-to: type=gha,scope=identity-service,mode=max + + - name: Alert Slack on failure + if: failure() && env.SLACK_DAILY_DEPLOY_WEBHOOK != '' + env: + SLACK_DAILY_DEPLOY_WEBHOOK: ${{ secrets.SLACK_DAILY_DEPLOY_WEBHOOK }} + JOB_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + run: | + json_content=$(cat <" } + } + ]} + EOF + ) + curl -f -X POST -H 'Content-type: application/json' \ + --data "$json_content" \ + "$SLACK_DAILY_DEPLOY_WEBHOOK" diff --git a/packages/identity-service/sequelize/migrations/20191107223636-create-viewed-field.js b/packages/identity-service/sequelize/migrations/20191107223636-create-viewed-field.js index 41db632793a..27108209a4a 100644 --- a/packages/identity-service/sequelize/migrations/20191107223636-create-viewed-field.js +++ b/packages/identity-service/sequelize/migrations/20191107223636-create-viewed-field.js @@ -1,5 +1,4 @@ 'use strict' -const models = require('../../src/models') module.exports = { up: (queryInterface, Sequelize) => { @@ -14,11 +13,12 @@ module.exports = { { transaction } ) - await models.Notification.update( - { - isViewed: false - }, - { transaction, where: { isRead: { [models.Sequelize.Op.ne]: null } } } + // Raw SQL instead of models.Notification.update — the Notification model + // was removed in #14207 but the Notifications table still exists in the + // schema, so this migration must keep running on fresh databases. + await queryInterface.sequelize.query( + 'UPDATE "Notifications" SET "isViewed" = false WHERE "isRead" IS NOT NULL', + { transaction } ) await queryInterface.changeColumn(