diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index f2342b06b..92ca3420f 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -4,6 +4,12 @@ on: pull_request: # Runs whenever a pull request is created or updated push: # Runs whenever a commit is pushed to the repository branches: [master, develop, beta, hotfix/*] # ...on any of these branches + workflow_call: # Runs whenever another workflow calls this workflow + inputs: + ref: + description: 'The branch or other ref to run this workflow on' + type: string + required: true workflow_dispatch: # Allows you to run this workflow manually from the Actions tab concurrency: @@ -18,29 +24,45 @@ env: SKIP_CLEANUP: true jobs: - build-and-test-and-maybe-deploy: + set-environment: # this job just a trick to DRY the environment logic + name: Set Environment runs-on: ubuntu-latest - environment: >- - ${{ - ( - (github.ref == 'refs/heads/master') && 'production' - ) || - ( - ( - (github.ref == 'refs/heads/develop') || - (github.ref == 'refs/heads/beta') || - startsWith(github.ref, 'refs/heads/hotfix/') || - startsWith(github.ref, 'refs/heads/release/') - ) && 'staging' - ) || - '' - }} env: - # SCRATCH_ENV comes from the GitHub Environment - # See https://github.com/scratchfoundation/scratch-www/settings/variables/actions - SCRATCH_SHOULD_DEPLOY: ${{ vars.SCRATCH_ENV != '' }} + GH_ENVIRONMENT: >- + ${{ + ( + (github.ref == 'refs/heads/master') && 'production' + ) || + ( + ( + (github.ref == 'refs/heads/develop') || + (github.ref == 'refs/heads/beta') || + startsWith(github.ref, 'refs/heads/hotfix/') || + startsWith(github.ref, 'refs/heads/release/') + ) && 'staging' + ) || + '' + }} + steps: + # apparently you're not allowed to have a job with no steps + - name: Report environment + run: | + echo "Environment: ${{ env.GH_ENVIRONMENT }}" + outputs: + environment: ${{ env.GH_ENVIRONMENT }} + should_deploy: ${{ (env.GH_ENVIRONMENT || '') != '' }} + build: + name: Build and Unit Tests + runs-on: ubuntu-latest + needs: set-environment + environment: ${{ needs.set-environment.outputs.environment }} + env: + SCRATCH_ENV: ${{ needs.set-environment.outputs.environment }} + SCRATCH_SHOULD_DEPLOY: ${{ needs.set-environment.outputs.should_deploy }} steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + with: + ref: ${{ inputs.ref }} # this should be empty to use `checkout`'s default UNLESS provided by workflow_call - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: cache: 'npm' @@ -48,7 +70,8 @@ jobs: - name: info run: | cat <<EOF - Scratch environment: ${{ vars.SCRATCH_ENV }} + Scratch environment: ${SCRATCH_ENV} + Should deploy: ${SCRATCH_SHOULD_DEPLOY} Node version: $(node --version) NPM version: $(npm --version) github.workflow: ${{ github.workflow }} @@ -56,11 +79,6 @@ jobs: github.head_ref: ${{ github.head_ref }} github.ref: ${{ github.ref }} EOF - - name: setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - run: pip install s3cmd==2.4.0 - run: npm --production=false ci - run: mkdir -p ./test/results - name: lint @@ -77,7 +95,6 @@ jobs: CLOUDDATA_HOST: ${{ secrets.CLOUDDATA_HOST }} PROJECT_HOST: ${{ secrets.PROJECT_HOST }} STATIC_HOST: ${{ secrets.STATIC_HOST }} - SCRATCH_ENV: ${{ vars.SCRATCH_ENV }} ONBOARDING_TEST_ACTIVE: "${{ vars.ONBOARDING_TEST_ACTIVE }}" ONBOARDING_TEST_PROJECT_IDS: "${{ vars.ONBOARDING_TEST_PROJECT_IDS }}" ONBOARDING_TESTING_STARTING_DATE: "${{ vars.ONBOARDING_TESTING_STARTING_DATE }}" @@ -92,8 +109,75 @@ jobs: JEST_JUNIT_OUTPUT_NAME=localization-jest-results.xml npm run test:unit:jest:localization -- --reporters=jest-junit npm run test:unit:tap -- --output-file ./test/results/unit-raw.tap npm run test:unit:convertReportToXunit + - name: compress artifacts + if: ${{ needs.set-environment.outputs.should_deploy == 'true' }} + env: + ZSTD_NBTHREADS: 0 # tell zstd to automatically choose thread count + run: | + mkdir -p artifacts/ + tar -cavf artifacts/build.tar.zst build + - name: "upload artifact: build" + if: ${{ needs.set-environment.outputs.should_deploy == 'true' }} + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4 + with: + name: build + path: artifacts/build.tar.zst + compression-level: 0 # don't re-compress compressed data + - name: save node_modules for other jobs + if: ${{ needs.set-environment.outputs.should_deploy == 'true' }} + uses: actions/cache/save@v4 + with: + path: node_modules + key: ${{ runner.os }}-node_modules-${{ hashFiles('.nvmrc', 'package-lock.json') }} + deploy: + name: Deploy + runs-on: ubuntu-latest + needs: [set-environment, build] + environment: ${{ needs.set-environment.outputs.environment }} + env: + SCRATCH_ENV: ${{ needs.set-environment.outputs.environment }} + if: ${{ needs.set-environment.outputs.should_deploy == 'true' }} + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + with: + ref: ${{ inputs.ref }} # this should be empty to use `checkout`'s default UNLESS provided by workflow_call + - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 + with: + node-version-file: '.nvmrc' + - name: info + run: | + cat <<EOF + Scratch environment: ${SCRATCH_ENV} + Node version: $(node --version) + NPM version: $(npm --version) + EOF + - name: retrieve node_modules + uses: actions/cache/restore@v4 + with: + fail-on-cache-miss: true + path: node_modules + key: ${{ runner.os }}-node_modules-${{ hashFiles('.nvmrc', 'package-lock.json') }} + - name: setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + - run: pip install s3cmd==2.4.0 + - name: download artifacts + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4 + with: + # if `name` is not specified, it will download all artifacts + path: artifacts/ + # upload-artifact makes a ZIP file with the provided `name` (default: `artifact`) + # by default, download-artifact will extract that ZIP file into a subdirectory with the same name + merge-multiple: true # don't make a subdirectory for each artifact name + - name: extract artifacts + env: + ZSTD_NBTHREADS: 0 # tell zstd to automatically choose thread count + run: | + ls -lRh artifacts/ + tar -xavf artifacts/build.tar.zst - name: deploy - if: ${{ env.SCRATCH_SHOULD_DEPLOY == 'true' }} + # This also uses SCRATCH_ENV, defined at the job level run: npm run deploy env: S3_LOCAL_DIR: build @@ -103,23 +187,51 @@ jobs: FASTLY_API_KEY: ${{ secrets.FASTLY_API_KEY }} FASTLY_SERVICE_ID: ${{ secrets.FASTLY_SERVICE_ID }} SCRATCH_BRANCH: ${{ github.ref_name }} - SCRATCH_ENV: ${{ vars.SCRATCH_ENV }} SLACK_WEBHOOK_CIRCLECI_NOTIFICATIONS: ${{ secrets.SLACK_WEBHOOK_CIRCLECI_NOTIFICATIONS }} # TODO: rename or replace SLACK_WEBHOOK_ENGINEERING: ${{ secrets.SLACK_WEBHOOK_ENGINEERING }} SLACK_WEBHOOK_MODS: ${{ secrets.SLACK_WEBHOOK_MODS }} RADISH_URL: ${{ vars.RADISH_URL }} - - name: integration tests - if: ${{ env.SCRATCH_SHOULD_DEPLOY == 'true' }} + integration-tests: + name: Production Integration Tests + runs-on: ubuntu-latest + needs: [set-environment, deploy] + environment: ${{ needs.set-environment.outputs.environment }} + # GHA can't reach staging + # TODO: Run integration tests against localhost? Not only would that let us test any and all branches, + # but we could also, I dunno, consider fully testing _before_ we deploy? :sweat_smile: + if: ${{ needs.set-environment.outputs.environment == 'production' }} + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + with: + ref: ${{ inputs.ref }} # this should be empty to use `checkout`'s default UNLESS provided by workflow_call + - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 + with: + node-version-file: '.nvmrc' + - name: retrieve node_modules + uses: actions/cache/restore@v4 + with: + fail-on-cache-miss: true + path: node_modules + key: ${{ runner.os }}-node_modules-${{ hashFiles('.nvmrc', 'package-lock.json') }} + - name: download artifacts + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4 + with: + # if `name` is not specified, it will download all artifacts + path: artifacts/ + # upload-artifact makes a ZIP file with the provided `name` (default: `artifact`) + # by default, download-artifact will extract that ZIP file into a subdirectory with the same name + merge-multiple: true # don't make a subdirectory for each artifact name + - name: extract artifacts + env: + ZSTD_NBTHREADS: 0 # tell zstd to automatically choose thread count run: | - if [ '${{ vars.SCRATCH_ENV }}' == 'production' ]; then - # if the health test fails, there's no point in trying to run the integration tests - npm run test:health - # health test succeeded, so proceed with integration tests - JEST_JUNIT_OUTPUT_NAME=integration-jest-results.xml npm run test:integration -- --reporters=jest-junit - else - echo "Skipping integration tests for non-production environment" - echo "Please run the integration tests manually if necessary" - fi + tar -xavf artifacts/build.tar.zst + - name: integration tests + run: | + # if the health test fails, there's no point in trying to run the integration tests + npm run test:health + # health test succeeded, so proceed with integration tests + JEST_JUNIT_OUTPUT_NAME=integration-jest-results.xml npm run test:integration -- --reporters=jest-junit env: ROOT_URL: ${{ secrets.ROOT_URL }} @@ -144,11 +256,3 @@ jobs: OWNED_UNSHARED_SCRATCH2_PROJECT_ID: ${{ secrets.OWNED_UNSHARED_SCRATCH2_PROJECT_ID }} TEST_STUDIO_ID: ${{ secrets.TEST_STUDIO_ID }} RATE_LIMIT_CHECK: ${{ secrets.RATE_LIMIT_CHECK }} - - name: compress artifact - if: ${{ env.SCRATCH_SHOULD_DEPLOY == 'true' }} - run: tar -czvf build.tgz build - - name: upload artifact - if: ${{ env.SCRATCH_SHOULD_DEPLOY == 'true' }} - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4 - with: - path: build.tgz diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index f6a8f00f9..f09e9f307 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -1,6 +1,6 @@ name: Create release branch and PRs -# Controls when the action will run. +# Controls when the action will run. on: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -12,6 +12,9 @@ jobs: # The type of runner that the job will run on runs-on: ubuntu-latest + outputs: + branch: ${{ steps.vars.outputs.branch }} + # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it @@ -47,4 +50,10 @@ jobs: pr_title: "[Master] ${{ steps.vars.outputs.branch }}" github_token: ${{ secrets.GITHUB_TOKEN }} pr_allow_empty: true - + call-ci-cd: + name: Call CI/CD workflow + needs: build + uses: ./.github/workflows/ci-cd.yml + secrets: inherit + with: + ref: ${{ needs.build.outputs.branch }} diff --git a/package-lock.json b/package-lock.json index 1b6f82694..094ff0ea9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,12 +23,12 @@ "react-twitter-embed": "3.0.3", "react-use": "17.6.0", "scratch-parser": "6.0.0", - "scratch-storage": "^4.0.69" + "scratch-storage": "^4.0.91" }, "devDependencies": { "@babel/cli": "7.26.4", - "@babel/core": "7.26.9", - "@babel/eslint-parser": "7.26.8", + "@babel/core": "7.26.10", + "@babel/eslint-parser": "7.26.10", "@babel/plugin-syntax-dynamic-import": "7.8.3", "@babel/plugin-transform-async-to-generator": "7.25.9", "@babel/plugin-transform-object-rest-spread": "7.25.9", @@ -42,7 +42,7 @@ "@scratch/scratch-gui": "^11.1.0-spork.15", "@types/jest": "29.5.14", "async": "3.2.6", - "autoprefixer": "10.4.20", + "autoprefixer": "10.4.21", "babel-loader": "8.4.1", "babel-plugin-transform-require-context": "0.1.1", "bowser": "1.9.4", @@ -110,10 +110,10 @@ "redux-mock-store": "1.5.5", "redux-thunk": "2.4.2", "regenerator-runtime": "0.13.9", - "sass": "1.85.1", + "sass": "1.86.0", "sass-loader": "10.5.2", - "scratch-l10n": "5.0.152", - "selenium-webdriver": "4.29.0", + "scratch-l10n": "5.0.180", + "selenium-webdriver": "4.30.0", "slick-carousel": "1.8.1", "stream-browserify": "3.0.0", "style-loader": "4.0.0", @@ -240,22 +240,22 @@ } }, "node_modules/@babel/core": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.9.tgz", - "integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.9", + "@babel/generator": "^7.26.10", "@babel/helper-compilation-targets": "^7.26.5", "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.9", - "@babel/parser": "^7.26.9", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.9", - "@babel/types": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -271,9 +271,9 @@ } }, "node_modules/@babel/eslint-parser": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.26.8.tgz", - "integrity": "sha512-3tBctaHRW6xSub26z7n8uyOTwwUsCdvIug/oxBH9n6yCO5hMj2vwDJAo7RbBMKrM7P+W2j61zLKviJQFGOYKMg==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.26.10.tgz", + "integrity": "sha512-QsfQZr4AiLpKqn7fz+j7SN+f43z2DZCgGyYbNJ2vJOqKfG4E6MZer1+jqGZqKJaxq/gdO2DC/nUu45+pOL5p2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -290,14 +290,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz", - "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.10.tgz", + "integrity": "sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9", + "@babel/parser": "^7.26.10", + "@babel/types": "^7.26.10", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -558,27 +558,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz", - "integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz", + "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==", "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.26.9", - "@babel/types": "^7.26.9" + "@babel/types": "^7.26.10" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz", - "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz", + "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.26.9" + "@babel/types": "^7.26.10" }, "bin": { "parser": "bin/babel-parser.js" @@ -2029,17 +2029,17 @@ } }, "node_modules/@babel/traverse": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.9.tgz", - "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.10.tgz", + "integrity": "sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.9", - "@babel/parser": "^7.26.9", + "@babel/generator": "^7.26.10", + "@babel/parser": "^7.26.10", "@babel/template": "^7.26.9", - "@babel/types": "^7.26.9", + "@babel/types": "^7.26.10", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2048,9 +2048,9 @@ } }, "node_modules/@babel/types": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz", - "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", + "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3925,6 +3925,39 @@ "react": "^16.0.0" } }, + "node_modules/@scratch/scratch-gui/node_modules/scratch-l10n": { + "version": "5.0.152", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-5.0.152.tgz", + "integrity": "sha512-tqK+2KRIFNyJBq53rwzx4J2pNcORJYp+spMfYQf8CNJI9iDlA4a6Q6twofW+1PhP8NFQIwo1r9T1WZdv+yaj3A==", + "dev": true, + "license": "AGPL-3.0-only", + "dependencies": { + "@transifex/api": "4.3.0", + "download": "8.0.0", + "transifex": "1.6.6" + }, + "bin": { + "build-i18n-src": "scripts/build-i18n-src.js", + "tx-push-src": "scripts/tx-push-src.js" + } + }, + "node_modules/@scratch/scratch-gui/node_modules/scratch-storage": { + "version": "4.0.70", + "resolved": "https://registry.npmjs.org/scratch-storage/-/scratch-storage-4.0.70.tgz", + "integrity": "sha512-iuK6bcr01gqxhL2CB8kvob4pTe7mQJbxQu0Y3T3oFDHIioIqmNTkgGdXICRrXW/hc3W7vjsh7XkILLxYCSmUAw==", + "dev": true, + "license": "AGPL-3.0-only", + "dependencies": { + "@babel/runtime": "^7.21.0", + "arraybuffer-loader": "^1.0.3", + "base64-js": "^1.3.0", + "buffer": "6.0.3", + "cross-fetch": "^4.1.0", + "fastestsmallesttextencoderdecoder": "^1.0.7", + "js-md5": "^0.7.3", + "minilog": "^3.1.0" + } + }, "node_modules/@scratch/scratch-render": { "version": "11.1.0-spork.15", "resolved": "https://registry.npmjs.org/@scratch/scratch-render/-/scratch-render-11.1.0-spork.15.tgz", @@ -4052,6 +4085,23 @@ "microee": "0.0.6" } }, + "node_modules/@scratch/scratch-vm/node_modules/scratch-storage": { + "version": "4.0.70", + "resolved": "https://registry.npmjs.org/scratch-storage/-/scratch-storage-4.0.70.tgz", + "integrity": "sha512-iuK6bcr01gqxhL2CB8kvob4pTe7mQJbxQu0Y3T3oFDHIioIqmNTkgGdXICRrXW/hc3W7vjsh7XkILLxYCSmUAw==", + "dev": true, + "license": "AGPL-3.0-only", + "dependencies": { + "@babel/runtime": "^7.21.0", + "arraybuffer-loader": "^1.0.3", + "base64-js": "^1.3.0", + "buffer": "6.0.3", + "cross-fetch": "^4.1.0", + "fastestsmallesttextencoderdecoder": "^1.0.7", + "js-md5": "^0.7.3", + "minilog": "^3.1.0" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -5605,9 +5655,9 @@ "license": "MIT" }, "node_modules/autoprefixer": { - "version": "10.4.20", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", - "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", "dev": true, "funding": [ { @@ -5625,11 +5675,11 @@ ], "license": "MIT", "dependencies": { - "browserslist": "^4.23.3", - "caniuse-lite": "^1.0.30001646", + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", - "picocolors": "^1.0.1", + "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "bin": { @@ -6930,9 +6980,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001700", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz", - "integrity": "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==", + "version": "1.0.30001703", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001703.tgz", + "integrity": "sha512-kRlAGTRWgPsOj7oARC9m1okJEXdL/8fekFVcxA8Hl7GH4r/sN4OJn/i6Flde373T50KS7Y37oFbMwlE8+F42kQ==", "dev": true, "funding": [ { @@ -22412,9 +22462,9 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.85.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.85.1.tgz", - "integrity": "sha512-Uk8WpxM5v+0cMR0XjX9KfRIacmSG86RH4DCCZjLU2rFh5tyutt9siAXJ7G+YfxQ99Q6wrRMbMlVl6KqUms71ag==", + "version": "1.86.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.0.tgz", + "integrity": "sha512-zV8vGUld/+mP4KbMLJMX7TyGCuUp7hnkOScgCMsWuHtns8CWBoz+vmEhoGMXsaJrbUP8gj+F1dLvVe79sK8UdA==", "dev": true, "license": "MIT", "dependencies": { @@ -22638,9 +22688,9 @@ } }, "node_modules/scratch-l10n": { - "version": "5.0.152", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-5.0.152.tgz", - "integrity": "sha512-tqK+2KRIFNyJBq53rwzx4J2pNcORJYp+spMfYQf8CNJI9iDlA4a6Q6twofW+1PhP8NFQIwo1r9T1WZdv+yaj3A==", + "version": "5.0.180", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-5.0.180.tgz", + "integrity": "sha512-o7V5dV3ldrTrPF/YwijUBwBCN+KZ2cj7EBa3KSHrhjtF5UpazKavv3TgXWFfBMHh5Gp5ZfljMnfdyyhBPh9sZw==", "dev": true, "license": "AGPL-3.0-only", "dependencies": { @@ -22761,9 +22811,9 @@ } }, "node_modules/scratch-storage": { - "version": "4.0.70", - "resolved": "https://registry.npmjs.org/scratch-storage/-/scratch-storage-4.0.70.tgz", - "integrity": "sha512-iuK6bcr01gqxhL2CB8kvob4pTe7mQJbxQu0Y3T3oFDHIioIqmNTkgGdXICRrXW/hc3W7vjsh7XkILLxYCSmUAw==", + "version": "4.0.92", + "resolved": "https://registry.npmjs.org/scratch-storage/-/scratch-storage-4.0.92.tgz", + "integrity": "sha512-OHv4A6pvzUopGJ0ATM6nQUZVoBVbw2VrZXZGpi7EFo9v32FVD6tv5mt7bI05MI6uJMJt1oPr7qbXQ1KhdtrTog==", "license": "AGPL-3.0-only", "dependencies": { "@babel/runtime": "^7.21.0", @@ -22845,9 +22895,9 @@ "license": "MIT" }, "node_modules/selenium-webdriver": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.29.0.tgz", - "integrity": "sha512-8XPGtDoji5xk7ZUCzFT1rqHmCp67DCzESsttId7DzmrJmlTRmRLF6X918rbwclcH89amcBNM4zB3lVPj404I0g==", + "version": "4.30.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.30.0.tgz", + "integrity": "sha512-3DGtQI/xyAg05SrqzzpFaXRWYL+Kku3fsikCoBaxApKzhBMUX5UiHdPb2je2qKMf2PjJiEFaj0L5xELHYRbYMA==", "dev": true, "funding": [ { diff --git a/package.json b/package.json index 19c4e2dd5..ebae01601 100644 --- a/package.json +++ b/package.json @@ -58,12 +58,12 @@ "react-twitter-embed": "3.0.3", "react-use": "17.6.0", "scratch-parser": "6.0.0", - "scratch-storage": "^4.0.69" + "scratch-storage": "^4.0.91" }, "devDependencies": { "@babel/cli": "7.26.4", - "@babel/core": "7.26.9", - "@babel/eslint-parser": "7.26.8", + "@babel/core": "7.26.10", + "@babel/eslint-parser": "7.26.10", "@babel/plugin-syntax-dynamic-import": "7.8.3", "@babel/plugin-transform-async-to-generator": "7.25.9", "@babel/plugin-transform-object-rest-spread": "7.25.9", @@ -77,7 +77,7 @@ "@scratch/scratch-gui": "^11.1.0-spork.15", "@types/jest": "29.5.14", "async": "3.2.6", - "autoprefixer": "10.4.20", + "autoprefixer": "10.4.21", "babel-loader": "8.4.1", "babel-plugin-transform-require-context": "0.1.1", "bowser": "1.9.4", @@ -145,10 +145,10 @@ "redux-mock-store": "1.5.5", "redux-thunk": "2.4.2", "regenerator-runtime": "0.13.9", - "sass": "1.85.1", + "sass": "1.86.0", "sass-loader": "10.5.2", - "scratch-l10n": "5.0.152", - "selenium-webdriver": "4.29.0", + "scratch-l10n": "5.0.180", + "selenium-webdriver": "4.30.0", "slick-carousel": "1.8.1", "stream-browserify": "3.0.0", "style-loader": "4.0.0",