diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index 9e3198100..000000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1 +0,0 @@ -* @splitio/sdk diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index 4ab91ee5c..000000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,7 +0,0 @@ -# JavaScript SDK - -## What did you accomplish? - -## How do we test the changes introduced in this PR? - -## Extra Notes diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml deleted file mode 100644 index b0e1105f0..000000000 --- a/.github/workflows/ci-cd.yml +++ /dev/null @@ -1,153 +0,0 @@ -name: ci-cd -on: - pull_request: - branches: - - main - - development - push: - branches: - - '*' - -env: - PUPPETEER_SKIP_DOWNLOAD: 'true' - -concurrency: - group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.run_number || github.event.pull_request.number }} - cancel-in-progress: true - -permissions: - contents: read - id-token: write - -jobs: - build: - name: Build - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v5 - - - name: Install Redis - run: | - sudo add-apt-repository ppa:redislabs/redis - sudo apt-get install -y redis-tools redis-server - - - name: Check Redis - run: redis-cli ping - - - name: Setup Node.js - uses: actions/setup-node@v6 - with: - node-version: 'lts/*' - cache: 'npm' - - - name: npm ci - run: npm ci - - - name: Setup Chrome - uses: browser-actions/setup-chrome@19ae4b339ee18925ab85cf12c1041150ea4a44c8 # v1 - with: - chrome-version: '125' - - name: Set CHROME_BIN - run: echo "CHROME_BIN=$(which chrome)" >> $GITHUB_ENV - - - name: npm ts tests - run: npm run test-ts-decls - - - name: npm check - run: npm run check - - - name: npm test-browser - run: npm run test-browser - - - name: npm test-node - run: npm run test-node - - - name: npm build - run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build - - - name: Store assets - if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/main') }} - uses: actions/upload-artifact@v5 - with: - name: assets - path: umd/ - retention-days: 1 - - upload-stage: - name: Upload assets - runs-on: ubuntu-latest - needs: build - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} - strategy: - matrix: - environment: - - stage - include: - - environment: stage - account_id: "079419646996" - bucket: split-public-stage - - steps: - - name: Download assets - uses: actions/download-artifact@v6 - with: - name: assets - path: umd - - - name: Display structure of assets - run: ls -R - working-directory: umd - - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: arn:aws:iam::${{ matrix.account_id }}:role/gha-public-assets-role - aws-region: us-east-1 - - - name: Upload to S3 - run: aws s3 sync $SOURCE_DIR s3://$BUCKET/$DEST_DIR $ARGS - env: - BUCKET: ${{ matrix.bucket }} - SOURCE_DIR: ./umd - DEST_DIR: sdk - ARGS: --acl public-read --follow-symlinks --cache-control max-age=31536000,public - - upload-prod: - name: Upload assets - runs-on: ubuntu-latest - needs: build - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} - strategy: - matrix: - environment: - - prod - include: - - environment: prod - account_id: "825951051969" - bucket: split-public - - steps: - - name: Download assets - uses: actions/download-artifact@v6 - with: - name: assets - path: umd - - - name: Display structure of assets - run: ls -R - working-directory: umd - - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: arn:aws:iam::${{ matrix.account_id }}:role/gha-public-assets-role - aws-region: us-east-1 - - - name: Upload to S3 - run: aws s3 sync $SOURCE_DIR s3://$BUCKET/$DEST_DIR $ARGS - env: - BUCKET: ${{ matrix.bucket }} - SOURCE_DIR: ./umd - DEST_DIR: sdk - ARGS: --acl public-read --follow-symlinks --cache-control max-age=31536000,public diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml deleted file mode 100644 index a81b328b1..000000000 --- a/.github/workflows/sonar-scan.yml +++ /dev/null @@ -1,66 +0,0 @@ -name: sonar-scan -on: - pull_request: - branches: - - main - - development - push: - branches: - - main - - development - -jobs: - build: - name: Build - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v5 - with: - fetch-depth: 0 - - - name: Set up Node.js - uses: actions/setup-node@v6 - with: - node-version: 'lts/*' - cache: 'npm' - - - name: npm CI - run: npm ci - - - name: npm Check - run: npm run check - - - name: npm Build - run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build - - - name: SonarQube Scan (Push) - if: github.event_name == 'push' - uses: SonarSource/sonarqube-scan-action@v6 - env: - SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }} - with: - projectBaseDir: . - args: > - -Dsonar.host.url=${{ secrets.SONARQUBE_HOST }} - -Dsonar.projectName=${{ github.event.repository.name }} - -Dsonar.projectKey=${{ github.event.repository.name }} - -Dsonar.links.ci="https://github.com/splitio/${{ github.event.repository.name }}/actions" - -Dsonar.links.scm="https://github.com/splitio/${{ github.event.repository.name }}" - - - name: SonarQube Scan (Pull Request) - if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository - uses: SonarSource/sonarqube-scan-action@v6 - env: - SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }} - with: - projectBaseDir: . - args: > - -Dsonar.host.url=${{ secrets.SONARQUBE_HOST }} - -Dsonar.projectName=${{ github.event.repository.name }} - -Dsonar.projectKey=${{ github.event.repository.name }} - -Dsonar.links.ci="https://github.com/splitio/${{ github.event.repository.name }}/actions" - -Dsonar.links.scm="https://github.com/splitio/${{ github.event.repository.name }}" - -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} - -Dsonar.pullrequest.branch=${{ github.event.pull_request.head.ref }} - -Dsonar.pullrequest.base=${{ github.event.pull_request.base.ref }} diff --git a/.github/workflows/update-notice-year.yml b/.github/workflows/update-notice-year.yml deleted file mode 100644 index 440dacbc0..000000000 --- a/.github/workflows/update-notice-year.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Update Notice Year - -on: - schedule: - - cron: "0 3 1 1 *" # 03:00 AM on January 1 - -permissions: - contents: write - pull-requests: write - -jobs: - test: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set Current year - run: "echo CURRENT=$(date +%Y) >> $GITHUB_ENV" - - - name: Set Previous Year - run: "echo PREVIOUS=$(($CURRENT-1)) >> $GITHUB_ENV" - - - name: Update NOTICE - uses: jacobtomlinson/gha-find-replace@v3 - with: - find: ${{ env.PREVIOUS }} - replace: ${{ env.CURRENT }} - include: "NOTICE" - regex: false - - - name: Commit files - run: | - git config user.name 'github-actions[bot]' - git config user.email 'github-actions[bot]@users.noreply.github.com' - git commit -m "Updated Notice Year" -a - - - name: Create Pull Request - uses: peter-evans/create-pull-request@v5 - with: - token: ${{ secrets.GITHUB_TOKEN }} - title: Update Notice Year - branch: update-notice diff --git a/.harness/ci-cd.yaml b/.harness/ci-cd.yaml new file mode 100644 index 000000000..d89ca3cda --- /dev/null +++ b/.harness/ci-cd.yaml @@ -0,0 +1,150 @@ +pipeline: + name: javascript-client + identifier: javascriptclient + projectIdentifier: Harness_Split + orgIdentifier: PROD + tags: {} + properties: + ci: + codebase: + connectorRef: fmegithubharnessgitops + repoName: javascript-client + build: <+input> + stages: + - stage: + name: Check-Test-Build-Upload + identifier: Checkout_code + description: "" + type: CI + spec: + cloneCodebase: true + caching: + enabled: true + override: true + paths: [] + platform: + os: Linux + arch: Amd64 + runtime: + type: Cloud + spec: + size: small + imageSpec: + imageName: ubuntu-latest + buildIntelligence: + enabled: false + execution: + steps: + - step: + type: Action + name: Set up Node.js + identifier: Set_up_Nodejs + spec: + uses: dcodeIO/setup-node-nvm@master + with: + node-version: lts/* + - step: + type: Run + name: Install Redis + identifier: Install_Redis + spec: + shell: Sh + command: |- + sudo add-apt-repository ppa:redislabs/redis + sudo apt-get install -y redis-tools redis-server + - step: + type: Run + name: Check Redis + identifier: Check_Redis + spec: + shell: Sh + command: redis-cli ping + - step: + type: Run + name: Install Chrome + identifier: Install_Chrome + spec: + shell: Bash + command: |- + curl -fsSL https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -o /tmp/chrome.deb + apt-get update -qq && apt-get install -y -qq /tmp/chrome.deb || true + # Fallback: install via chromium if the .deb install failed + which google-chrome-stable || apt-get install -y -qq chromium-browser + CHROME_BIN=$(which google-chrome-stable || which chromium-browser || which chromium) + echo "CHROME_BIN=$CHROME_BIN" + - step: + type: Run + name: npm ci + identifier: npm_ci + spec: + shell: Sh + command: npm ci + envVariables: + PUPPETEER_SKIP_DOWNLOAD: "true" + - step: + type: Run + name: npm ts tests + identifier: npm_ts_tests + spec: + shell: Sh + command: npm run test-ts-decls + - step: + type: Run + name: npm run check + identifier: npm_run_check + spec: + shell: Sh + command: npm run check + - step: + type: Run + name: npm test-browser + identifier: npm_test_browser + spec: + shell: Bash + command: |- + CHROME_BIN=$(which google-chrome-stable || which chromium-browser || which chromium) + export CHROME_BIN + npm run test-browser + - step: + type: Run + name: npm test-node + identifier: npm_test_node + spec: + shell: Sh + command: npm run test-node + - step: + type: Run + name: npm run build + identifier: npm_run_build + spec: + shell: Sh + command: BUILD_BRANCH=<+codebase.branch> npm run build + - parallel: + - step: + type: Run + name: upload dev assets to CDN + identifier: upload_dev_assets_to_CDN + spec: + shell: Sh + command: |- + aws s3 sync ./umd s3://split-public-stage/sdk --acl public-read --follow-symlinks --cache-control max-age=31536000,public + connectorRef: artifacts + envVariables: + AWS_DEFAULT_REGION: us-east-1 + when: + stageStatus: Success + condition: <+trigger.event> == "PUSH" && <+trigger.branch> == "development" + - step: + type: Run + name: upload prod assets to CDN + identifier: upload_prod_assets_to_CDN + spec: + shell: Sh + command: |- + aws s3 sync ./umd s3://split-public/sdk --acl public-read --follow-symlinks --cache-control max-age=31536000,public + connectorRef: artifacts + envVariables: + AWS_DEFAULT_REGION: us-east-1 + when: + stageStatus: Success + condition: <+trigger.event> == "PUSH" && <+trigger.branch> == "main" diff --git a/.harness/input-set.yaml b/.harness/input-set.yaml new file mode 100644 index 000000000..6cd665e2f --- /dev/null +++ b/.harness/input-set.yaml @@ -0,0 +1,14 @@ +inputSet: + name: javascript-client + identifier: javascriptclient + orgIdentifier: PROD + projectIdentifier: Harness_Split + pipeline: + identifier: javascriptclient + properties: + ci: + codebase: + build: + type: branch + spec: + branch: <+trigger.branch> diff --git a/src/__tests__/consumer/node_redis.spec.js b/src/__tests__/consumer/node_redis.spec.js index a9da4544b..de5d2bfe9 100644 --- a/src/__tests__/consumer/node_redis.spec.js +++ b/src/__tests__/consumer/node_redis.spec.js @@ -43,7 +43,7 @@ const config = { impressionsMode: 'DEBUG' }, startup: { - readyTimeout: 36000 // 10hs + readyTimeout: 15 // 15 secs. Enough to connect to a local Redis, but avoids hanging the test suite if the connection never succeeds } }; const expectedConfig = '{"color":"brown"}'; @@ -71,25 +71,36 @@ const MOCKS = { /** * Initialize redis server and run a cli bash command to load redis with data to do the proper tests */ -const initializeRedisServer = (mock = '') => { +const initializeRedisServer = (assert, mock = '') => { // Simply pass the port that you want a Redis server to listen on. const server = new RedisServer(redisPort); const mockFileName = MOCKS[mock]; - const promise = new Promise((resolve, reject) => { + // If the server fails to start (e.g. port 6385 is already in use by a stale redis-server + // from a previous interrupted run) or the data cannot be loaded, fail and end the test + // right away. Otherwise the returned promise never settles and `tape` hangs forever. + const handleError = (err) => { + assert.fail(err); + assert.end(); + }; + + // The returned promise only resolves on success; on failure the test is already ended above, + // so the `.then` consumer never runs and there is no unhandled rejection to hang on. + const promise = new Promise((resolve) => { server .open() .then(() => { exec(`cat ./src/__tests__/mocks/${mockFileName}.txt | redis-cli -p ${redisPort}`, err => { if (err) { - reject(server); // Node.js couldn't execute the command + handleError(err); return; } resolve(server); }); - }); + }) + .catch(handleError); }); return promise; @@ -98,7 +109,7 @@ const initializeRedisServer = (mock = '') => { tape('Node.js Redis', function (t) { t.test('Regular usage - DEBUG strategy', assert => { - initializeRedisServer() + initializeRedisServer(assert) .then(async (server) => { const sdk = SplitFactory(config); const client = sdk.client(); @@ -223,7 +234,7 @@ tape('Node.js Redis', function (t) { t.test('Regular usage - OPTIMIZED strategy', assert => { config.sync.impressionsMode = OPTIMIZED; - initializeRedisServer() + initializeRedisServer(assert) .then(async (server) => { assert.equal(config.sync.impressionsMode, OPTIMIZED, 'impressionsMode should be OPTIMIZED'); const sdk = SplitFactory(config); @@ -349,7 +360,7 @@ tape('Node.js Redis', function (t) { t.test('Regular usage - NONE strategy', assert => { config.sync.impressionsMode = NONE; - initializeRedisServer() + initializeRedisServer(assert) .then(async (server) => { const expectedUniqueKeys = [ { 'f': 'UT_IN_SEGMENT', 'ks': ['UT_Segment_member', 'other'] }, @@ -549,7 +560,7 @@ tape('Node.js Redis', function (t) { }); t.test('Connection error', assert => { - initializeRedisServer() + initializeRedisServer(assert) .then((server) => { const sdk = SplitFactory({ ...config, @@ -607,7 +618,7 @@ tape('Node.js Redis', function (t) { }); t.test('Calling destroy with pending operations', assert => { - initializeRedisServer() + initializeRedisServer(assert) .then(async (server) => { const sdk = SplitFactory({ ...config, @@ -644,7 +655,7 @@ tape('Node.js Redis', function (t) { }); t.test('Check IP and Hostname in Redis', assert => { - initializeRedisServer() + initializeRedisServer(assert) .then(async (server) => { const configs = [ @@ -700,7 +711,7 @@ tape('Node.js Redis', function (t) { }); t.test('Getting treatments with flag sets', assert => { - initializeRedisServer('flag_sets') + initializeRedisServer(assert, 'flag_sets') .then(async (server) => { const sdk = SplitFactory(config);