From 3caee2faf590c8af12f97ad877e04ce4b3d3a91c Mon Sep 17 00:00:00 2001 From: Maribeth Moffatt Date: Tue, 3 Mar 2026 15:26:01 -0500 Subject: [PATCH 01/17] chore: improve gh-pages publishing steps (#9604) * fix: Fix gulpfiles related to publishing GitHub pages * chore: remove unused gulp tasks * feat: allow passing a remote to push gh-pages to * feat: add ability to skip syncing with main * feat: add gh workflow to publish ghpages * chore: update node version --------- Co-authored-by: Aaron Dodson --- .github/workflows/update-gh-pages.yml | 36 +++ packages/blockly/gulpfile.mjs | 25 +- packages/blockly/package.json | 5 +- .../blockly/scripts/gulpfiles/git_tasks.mjs | 223 +++++++++--------- .../scripts/gulpfiles/release_tasks.mjs | 59 ----- 5 files changed, 153 insertions(+), 195 deletions(-) create mode 100644 .github/workflows/update-gh-pages.yml diff --git a/.github/workflows/update-gh-pages.yml b/.github/workflows/update-gh-pages.yml new file mode 100644 index 000000000..e45aca688 --- /dev/null +++ b/.github/workflows/update-gh-pages.yml @@ -0,0 +1,36 @@ +# Manual workflow to update GitHub Pages from a chosen source branch. +# The gulp updateGithubPages task builds the repo and force-pushes to gh-pages. + +name: Update GitHub Pages + +on: + workflow_dispatch: + inputs: + source_branch: + description: 'Source branch to build and deploy to GitHub Pages' + required: true + type: string + default: main + +permissions: + contents: write + +jobs: + update-gh-pages: + timeout-minutes: 15 + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v5 + with: + ref: ${{ inputs.source_branch }} + fetch-depth: 0 + + - name: Use Node.js + uses: actions/setup-node@v5 + with: + node-version: 24.x + + - name: Update GitHub Pages + working-directory: ./packages/blockly + run: npm run updateGithubPages:staging diff --git a/packages/blockly/gulpfile.mjs b/packages/blockly/gulpfile.mjs index ad61bcb51..378d6ce5e 100644 --- a/packages/blockly/gulpfile.mjs +++ b/packages/blockly/gulpfile.mjs @@ -33,18 +33,9 @@ import { tsc, } from './scripts/gulpfiles/build_tasks.mjs'; import {docs} from './scripts/gulpfiles/docs_tasks.mjs'; -import { - createRC, - syncDevelop, - syncMaster, - updateGithubPages, -} from './scripts/gulpfiles/git_tasks.mjs'; +import {updateGithubPages} from './scripts/gulpfiles/git_tasks.mjs'; import {cleanReleaseDir, pack} from './scripts/gulpfiles/package_tasks.mjs'; -import { - publish, - publishBeta, - recompile, -} from './scripts/gulpfiles/release_tasks.mjs'; +import {publish, publishBeta} from './scripts/gulpfiles/release_tasks.mjs'; import { generators, interactiveMocha, @@ -72,7 +63,7 @@ export { prepareDemos, deployDemosBeta, deployDemos, - updateGithubPages as gitUpdateGithubPages, + updateGithubPages, } // Manually-invokable targets that also invoke prerequisites where @@ -86,15 +77,5 @@ export { generators as testGenerators, interactiveMocha, buildAdvancedCompilationTest, - createRC as gitCreateRC, docs, } - -// Legacy targets, to be deleted. -// -// prettier-ignore -export { - recompile, - syncDevelop as gitSyncDevelop, - syncMaster as gitSyncMaster, -} diff --git a/packages/blockly/package.json b/packages/blockly/package.json index ad4a58688..168d415b3 100644 --- a/packages/blockly/package.json +++ b/packages/blockly/package.json @@ -38,8 +38,6 @@ "prepareDemos": "gulp prepareDemos", "publish": "npm ci && gulp publish", "publish:beta": "npm ci && gulp publishBeta", - "recompile": "gulp recompile", - "release": "gulp gitCreateRC", "start": "npm run build && concurrently -n tsc,server \"tsc --watch --preserveWatchOutput --outDir \"build/src\" --declarationDir \"build/declarations\"\" \"http-server ./ -s -o /tests/playground.html -c-1\"", "tsc": "gulp tsc", "test": "gulp test", @@ -47,7 +45,8 @@ "test:generators": "gulp testGenerators", "test:mocha:interactive": "npm run build && concurrently -n tsc,server \"tsc --watch --preserveWatchOutput --outDir \"build/src\" --declarationDir \"build/declarations\"\" \"gulp interactiveMocha\"", "test:compile:advanced": "gulp buildAdvancedCompilationTest --debug", - "updateGithubPages": "npm ci && gulp gitUpdateGithubPages" + "updateGithubPages": "npm ci && gulp updateGithubPages --upstream", + "updateGithubPages:staging": "npm ci && gulp updateGithubPages --use-local" }, "exports": { ".": { diff --git a/packages/blockly/scripts/gulpfiles/git_tasks.mjs b/packages/blockly/scripts/gulpfiles/git_tasks.mjs index 2b08e16b3..6a68b54be 100644 --- a/packages/blockly/scripts/gulpfiles/git_tasks.mjs +++ b/packages/blockly/scripts/gulpfiles/git_tasks.mjs @@ -8,17 +8,36 @@ * @fileoverview Git-related gulp tasks for Blockly. */ + import * as gulp from 'gulp'; import {execSync} from 'child_process'; +import yargs from 'yargs'; +import { hideBin } from 'yargs/helpers'; import * as buildTasks from './build_tasks.mjs'; import * as packageTasks from './package_tasks.mjs'; -const UPSTREAM_URL = 'https://github.com/google/blockly.git'; +const UPSTREAM_URL = 'git@github.com:RaspberryPiFoundation/blockly.git'; + +// Use yargs to parse --remote argument +const argv = yargs(hideBin(process.argv)).option('remote', { + type: 'string', + describe: 'Remote to push gh-pages to', + demandOption: false +}).option('upstream', { + type: 'boolean', + describe: 'Push to RaspberryPiFoundation/blockly instead of origin', + demandOption: false +}).option('use-local', { + type: 'boolean', + describe: 'Build and push from current branch instead of syncing with main', + demandOption: false +}).help().argv; +const remoteToUse = argv.upstream ? UPSTREAM_URL : resolveRemote(argv.remote); /** * Extra paths to include in the gh_pages branch (beyond the normal - * contents of master / develop). Passed to shell unquoted, so can + * contents of main). Passed to shell unquoted, so can * include globs. */ const EXTRAS = [ @@ -28,140 +47,122 @@ const EXTRAS = [ 'build/*.loader.mjs', ]; -let upstream = null; - /** - * Get name of git remote for upstream (typically 'upstream', but this - * is just convention and can be changed.) - */ -function getUpstream() { - if (upstream) return upstream; - for (const line of String(execSync('git remote -v')).split('\n')) { - if (line.includes('google/blockly')) { - upstream = line.split('\t')[0]; - return upstream; - } - } - throw new Error('Unable to determine upstream URL'); -} - -/** - * Stash current state, check out the named branch, and sync with - * google/blockly. + * Stash current state, check out the named branch, and pull + * changes from RaspberryPiFoundation/blockly. */ function syncBranch(branchName) { return function(done) { execSync('git stash save -m "Stash for sync"', { stdio: 'inherit' }); checkoutBranch(branchName); execSync(`git pull ${UPSTREAM_URL} ${branchName}`, { stdio: 'inherit' }); - execSync(`git push origin ${branchName}`, { stdio: 'inherit' }); done(); }; } /** - * Stash current state, check out develop, and sync with - * google/blockly. + * Stash current state, check out main, and sync with + * RaspberryPiFoundation/blockly. */ -export function syncDevelop() { - return syncBranch('develop'); +export function syncMain() { + return syncBranch('main'); }; /** - * Stash current state, check out master, and sync with - * google/blockly. - */ -export function syncMaster() { - return syncBranch('master'); -}; - -/** - * Helper function: get a name for a rebuild branch. Format: - * rebuild_mm_dd_yyyy. - */ -function getRebuildBranchName() { - const date = new Date(); - const mm = date.getMonth() + 1; // Month, 0-11 - const dd = date.getDate(); // Day of the month, 1-31 - const yyyy = date.getFullYear(); - return `rebuild_${mm}_${dd}_${yyyy}`; -}; - -/** - * Helper function: get a name for a rebuild branch. Format: - * rebuild_yyyy_mm. - */ -function getRCBranchName() { - const date = new Date(); - const mm = date.getMonth() + 1; // Month, 0-11 - const yyyy = date.getFullYear(); - return `rc_${yyyy}_${mm}`; -}; - -/** - * If branch does not exist then create the branch. * If branch exists switch to branch. + * If branch does not exist then create the branch. */ function checkoutBranch(branchName) { - execSync(`git switch -c ${branchName}`, + execSync(`git switch ${branchName} || git switch -c ${branchName}`, { stdio: 'inherit' }); } /** - * Create and push an RC branch. - * Note that this pushes to google/blockly. - */ -export const createRC = gulp.series( - syncDevelop(), - function(done) { - const branchName = getRCBranchName(); - execSync(`git switch -C ${branchName}`, { stdio: 'inherit' }); - execSync(`git push ${UPSTREAM_URL} ${branchName}`, { stdio: 'inherit' }); - done(); - } -); - -/** Create the rebuild branch. */ -export function createRebuildBranch(done) { - const branchName = getRebuildBranchName(); - console.log(`make-rebuild-branch: creating branch ${branchName}`); - execSync(`git switch -C ${branchName}`, { stdio: 'inherit' }); - done(); -} - -/** Push the rebuild branch to origin. */ -export function pushRebuildBranch(done) { - console.log('push-rebuild-branch: committing rebuild'); - execSync('git commit -am "Rebuild"', { stdio: 'inherit' }); - const branchName = getRebuildBranchName(); - execSync(`git push origin ${branchName}`, { stdio: 'inherit' }); - console.log(`Branch ${branchName} pushed to GitHub.`); - console.log('Next step: create a pull request against develop.'); - done(); -} - -/** - * Update github pages with what is currently in develop. + * Update github pages with what is currently in main (or current branch if --use-local). * * Prerequisites (invoked): clean, build. + * + * Usage: + * gulp updateGithubPages # sync main, then use origin if exists + * gulp updateGithubPages --upstream # uses hardcoded upstream + * gulp updateGithubPages --remote # uses named remote + * gulp updateGithubPages --use-local # build from current branch, skip syncing main + * */ export const updateGithubPages = gulp.series( - function(done) { - execSync('git stash save -m "Stash for sync"', { stdio: 'inherit' }); - execSync('git switch -C gh-pages', { stdio: 'inherit' }); - execSync(`git fetch ${getUpstream()}`, { stdio: 'inherit' }); - execSync(`git reset --hard ${getUpstream()}/develop`, { stdio: 'inherit' }); - done(); - }, - buildTasks.cleanBuildDir, - packageTasks.cleanReleaseDir, - buildTasks.build, - function(done) { - // Extra paths (e.g. build/, dist/ etc.) are normally gitignored, - // so we have to force add. - execSync(`git add -f ${EXTRAS.join(' ')}`, {stdio: 'inherit'}); - execSync('git commit -am "Rebuild"', {stdio: 'inherit'}); - execSync(`git push ${UPSTREAM_URL} gh-pages --force`, {stdio: 'inherit'}); - done(); + function (done) { + if (!remoteToUse) { + const attemptedRemote = argv.remote || 'origin'; + const remoteLabel = argv.remote + ? `Remote '${attemptedRemote}'` + : "Remote 'origin' (default)"; + const errMsg = `${remoteLabel} not found in git remotes. ` + + 'Please add that remote or use --upstream.\n' + + 'Usage: gulp updateGithubPages [--remote | --upstream]'; + console.error(errMsg); + done(new Error(errMsg)); + return; + } + done(); + }, + function (done) { + if (!argv.useLocal) { + done(); + return; + } + const status = execSync('git status --porcelain', { encoding: 'utf8' }); + if (status.trim()) { + const errMsg = + 'You cannot push the local branch with uncommitted changes. ' + + 'Please commit or stash your changes first.'; + console.error(errMsg); + done(new Error(errMsg)); + return; + } + done(); + }, + function (done) { + if (argv.useLocal) { + done(); + return; + } + syncMain()(done); + }, + function(done) { + const sourceRef = argv.useLocal + ? execSync('git rev-parse HEAD', { encoding: 'utf8' }).trim() + : 'main'; + execSync('git switch -C gh-pages', { stdio: 'inherit' }); + execSync(`git reset --hard ${sourceRef}`, { stdio: 'inherit' }); + done(); + }, + buildTasks.cleanBuildDir, + packageTasks.cleanReleaseDir, + buildTasks.build, + function(done) { + // Extra paths (e.g. build/, dist/ etc.) are normally gitignored, + // so we have to force add. + execSync(`git add -f ${EXTRAS.join(' ')}`, {stdio: 'inherit'}); + execSync('git commit -am "Rebuild"', {stdio: 'inherit'}); + execSync(`git push ${remoteToUse} gh-pages --force`, {stdio: 'inherit'}); + done(); + } + ); + +/** + * Resolves which remote to use for pushing gh-pages. + * @param {string} remoteArg + * @returns {string|undefined} The remote name, or undefined if not found. + */ +function resolveRemote(remoteArg) { + const remoteName = remoteArg || 'origin'; + try { + const remotes = execSync('git remote', {encoding: 'utf8'}).split(/\r?\n/).map(r => r.trim()).filter(Boolean); + if (remotes.includes(remoteName)) { + return remoteName; + } + return undefined; + } catch (e) { + return undefined; } -); +} diff --git a/packages/blockly/scripts/gulpfiles/release_tasks.mjs b/packages/blockly/scripts/gulpfiles/release_tasks.mjs index a678a4f24..ca9c9ffa1 100644 --- a/packages/blockly/scripts/gulpfiles/release_tasks.mjs +++ b/packages/blockly/scripts/gulpfiles/release_tasks.mjs @@ -18,55 +18,6 @@ import * as packageTasks from './package_tasks.mjs'; import {getPackageJson} from './helper_tasks.mjs'; import {RELEASE_DIR} from './config.mjs'; - -// Gets the current major version. -function getMajorVersion() { - const { version } = getPackageJson(); - const re = new RegExp(/^(\d)./); - const match = re.exec(version); - if (!match[0]) { - return null; - } - console.log(match[0]); - return parseInt(match[0]); -} - -// Updates the version depending on user input. -function updateVersion(done, updateType) { - const majorVersion = getMajorVersion(); - if (!majorVersion) { - done(new Error('Something went wrong when getting the major version number.')); - } else if (!updateType) { - // User selected to cancel. - done(new Error('Cancelling process.')); - } - - switch (updateType.toLowerCase()) { - case 'major': - majorVersion++; - execSync(`npm --no-git-tag-version version ${majorVersion}.$(date +'%Y%m%d').0`, {stdio: 'inherit'}); - done(); - break; - case 'minor': - execSync(`npm --no-git-tag-version version ${majorVersion}.$(date +'%Y%m%d').0`, {stdio: 'inherit'}); - done(); - break; - case 'patch': - execSync(`npm --no-git-tag-version version patch`, {stdio: 'inherit'}); - done(); - break; - default: - done(new Error('Unexpected update type was chosen.')) - } -} - -// Prompt the user to figure out what kind of version update we should do. -function updateVersionPrompt(done) { - const releaseTypes = ['Major', 'Minor', 'Patch']; - const index = readlineSync.keyInSelect(releaseTypes, 'Which version type?'); - updateVersion(done, releaseTypes[index]); -} - // Checks with the user that they are on the correct git branch. function checkBranch(done) { const gitBranchName = execSync('git rev-parse --abbrev-ref HEAD').toString(); @@ -162,13 +113,3 @@ export const publishBeta = gulp.series( checkReleaseDir, loginAndPublishBeta ); - -// Switch to a new branch, update the version number, build Blockly -// and check in the resulting built files. -export const recompile = gulp.series( - gitTasks.syncDevelop(), - gitTasks.createRebuildBranch, - updateVersionPrompt, - packageTasks.pack, // Does clean + build. - gitTasks.pushRebuildBranch - ); From 14cbb9acbab4a817c4696b85468e2f8ac83af911 Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Wed, 4 Mar 2026 13:21:20 -0800 Subject: [PATCH 02/17] chore: Remove keyboard experimentation CI (#9609) --- .github/workflows/keyboard_plugin_test.yml | 66 ---------------------- 1 file changed, 66 deletions(-) delete mode 100644 .github/workflows/keyboard_plugin_test.yml diff --git a/.github/workflows/keyboard_plugin_test.yml b/.github/workflows/keyboard_plugin_test.yml deleted file mode 100644 index e64efe983..000000000 --- a/.github/workflows/keyboard_plugin_test.yml +++ /dev/null @@ -1,66 +0,0 @@ -# Workflow for running the keyboard navigation plugin's automated tests. - -name: Keyboard Navigation Automated Tests - -on: - workflow_dispatch: - pull_request: - push: - branches: - - main - -permissions: - contents: read - -jobs: - webdriverio_tests: - name: WebdriverIO tests - timeout-minutes: 10 - runs-on: ${{ matrix.os }} - - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - - steps: - - name: Checkout core Blockly - uses: actions/checkout@v5 - with: - path: core-blockly - - - name: Checkout keyboard navigation plugin - uses: actions/checkout@v5 - with: - repository: 'google/blockly-keyboard-experimentation' - ref: 'main' - path: blockly-keyboard-experimentation - - - name: Use Node.js 20.x - uses: actions/setup-node@v5 - with: - node-version: 20.x - - - name: NPM install - run: | - cd core-blockly - npm install - cd .. - cd blockly-keyboard-experimentation - npm install - cd .. - - - name: Link latest core main with plugin - run: | - cd core-blockly/packages/blockly - npm run package - cd dist - npm link - cd ../../../../blockly-keyboard-experimentation - npm link blockly - cd .. - - - name: Run keyboard navigation plugin tests - run: | - cd blockly-keyboard-experimentation - npm run test From a6325ed0e36f26d6f509f2f1950c9278e2c9fb67 Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Mon, 16 Mar 2026 12:57:59 -0700 Subject: [PATCH 03/17] fix: Fix a bug that could cause menus to scroll incorrectly on mouseover (#9603) * fix: Fix a bug that could cause menus to scroll incorrectly on mouseover * refactor: Simplify CSS --- packages/blockly/core/css.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/blockly/core/css.ts b/packages/blockly/core/css.ts index de9e682f8..c29f9f97c 100644 --- a/packages/blockly/core/css.ts +++ b/packages/blockly/core/css.ts @@ -452,17 +452,14 @@ input[type=number] { } /* State: selected/checked. */ -.blocklyMenuItemCheckbox { - height: 16px; - position: absolute; - width: 16px; -} - .blocklyMenuItemSelected .blocklyMenuItemCheckbox { background: url(<<>>/sprites.png) no-repeat -48px -16px; float: left; margin-left: -24px; + width: 16px; + height: 16px; position: static; /* Scroll with the menu. */ + display: block; } .blocklyMenuItemRtl .blocklyMenuItemCheckbox { From f6f5fcc6ad81a7964a4c70346e3a6465e44c2323 Mon Sep 17 00:00:00 2001 From: Maribeth Moffatt Date: Mon, 16 Mar 2026 16:10:40 -0400 Subject: [PATCH 04/17] chore: add workflow for versioning/publishing blockly (#9627) * chore: add workflow for versioning/publishing blockly * chore: add dry run option --- .github/workflows/build.yml | 4 +- .github/workflows/publish.yml | 93 ++++++++++++++++++++++++ package-lock.json | 128 ++++++++++++++++++++++++++++++++++ packages/blockly/package.json | 2 + 4 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f0cd08796..6fbacad19 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,7 +3,9 @@ name: Node.js CI -on: [pull_request] +on: + pull_request: + workflow_call: permissions: contents: read diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 000000000..194573bdd --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,93 @@ +name: Publish to npm + +on: + workflow_dispatch: + inputs: + dry_run: + description: 'Dry run' + required: false + default: false + type: boolean + +permissions: + contents: write + id-token: write + +jobs: + ci: + uses: ./.github/workflows/build.yml + + publish: + needs: ci + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v5 + with: + node-version: 22.x + registry-url: 'https://registry.npmjs.org' + + - name: Install dependencies + run: npm ci + + - name: Determine version bump + id: bump + working-directory: packages/blockly + run: | + RELEASE_TYPE=$(npx conventional-recommended-bump --preset conventionalcommits) + echo "release_type=$RELEASE_TYPE" >> "$GITHUB_OUTPUT" + echo "Recommended bump: $RELEASE_TYPE" + + - name: Apply version bump + working-directory: packages/blockly + run: npm version ${{ steps.bump.outputs.release_type }} --no-git-tag-version + + - name: Read new version + id: version + working-directory: packages/blockly + run: | + VERSION=$(node -p "require('./package.json').version") + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + echo "New version: $VERSION" + + - name: Commit and push version bump + if: ${{ !inputs.dry_run }} + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add packages/blockly/package.json package-lock.json + git commit -m "chore: release v${{ steps.version.outputs.version }}" + git push + + - name: Build package + if: ${{ !inputs.dry_run }} + working-directory: packages/blockly + run: npm run package + + - name: Publish to npm + if: ${{ !inputs.dry_run }} + working-directory: packages/blockly/dist + run: npm publish + + - name: Create tarball + if: ${{ !inputs.dry_run }} + working-directory: packages/blockly + run: npm pack ./dist + + - name: Create GitHub release + if: ${{ !inputs.dry_run }} + working-directory: packages/blockly + env: + GH_TOKEN: ${{ github.token }} + run: | + TARBALL=$(ls blockly-*.tgz) + gh release create "blockly-v${{ steps.version.outputs.version }}" "$TARBALL" \ + --repo "$GITHUB_REPOSITORY" \ + --title "blockly-v${{ steps.version.outputs.version }}" \ + --generate-notes diff --git a/package-lock.json b/package-lock.json index 1eb297536..778b4aafc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -298,6 +298,62 @@ "node": ">=v18" } }, + "node_modules/@conventional-changelog/git-client": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@conventional-changelog/git-client/-/git-client-2.6.0.tgz", + "integrity": "sha512-T+uPDciKf0/ioNNDpMGc8FDsehJClZP0yR3Q5MN6wE/Y/1QZ7F+80OgznnTCOlMEG4AV0LvH2UJi3C/nBnaBUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@simple-libs/child-process-utils": "^1.0.0", + "@simple-libs/stream-utils": "^1.2.0", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "conventional-commits-filter": "^5.0.0", + "conventional-commits-parser": "^6.3.0" + }, + "peerDependenciesMeta": { + "conventional-commits-filter": { + "optional": true + }, + "conventional-commits-parser": { + "optional": true + } + } + }, + "node_modules/@simple-libs/child-process-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@simple-libs/child-process-utils/-/child-process-utils-1.0.2.tgz", + "integrity": "sha512-/4R8QKnd/8agJynkNdJmNw2MBxuFTRcNFnE5Sg/G+jkSsV8/UBgULMzhizWWW42p8L5H7flImV2ATi79Ove2Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@simple-libs/stream-utils": "^1.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://ko-fi.com/dangreen" + } + }, + "node_modules/@simple-libs/stream-utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@simple-libs/stream-utils/-/stream-utils-1.2.0.tgz", + "integrity": "sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://ko-fi.com/dangreen" + } + }, "node_modules/@types/conventional-commits-parser": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.2.tgz", @@ -514,6 +570,26 @@ "node": ">=16" } }, + "node_modules/conventional-changelog-preset-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-5.0.0.tgz", + "integrity": "sha512-SetDSntXLk8Jh1NOAl1Gu5uLiCNSYenB5tm0YVeZKePRIgDW9lQImromTwLa3c/Gae298tsgOM+/CYT9XAl0NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/conventional-commits-filter": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-5.0.0.tgz", + "integrity": "sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/conventional-commits-parser": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", @@ -533,6 +609,56 @@ "node": ">=16" } }, + "node_modules/conventional-recommended-bump": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-11.2.0.tgz", + "integrity": "sha512-lqIdmw330QdMBgfL0e6+6q5OMKyIpy4OZNmepit6FS3GldhkG+70drZjuZ0A5NFpze5j85dlYs3GabQXl6sMHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@conventional-changelog/git-client": "^2.5.1", + "conventional-changelog-preset-loader": "^5.0.0", + "conventional-commits-filter": "^5.0.0", + "conventional-commits-parser": "^6.1.0", + "meow": "^13.0.0" + }, + "bin": { + "conventional-recommended-bump": "dist/cli/index.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/conventional-recommended-bump/node_modules/conventional-commits-parser": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-6.3.0.tgz", + "integrity": "sha512-RfOq/Cqy9xV9bOA8N+ZH6DlrDR+5S3Mi0B5kACEjESpE+AviIpAptx9a9cFpWCCvgRtWT+0BbUw+e1BZfts9jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@simple-libs/stream-utils": "^1.2.0", + "meow": "^13.0.0" + }, + "bin": { + "conventional-commits-parser": "dist/cli/index.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/conventional-recommended-bump/node_modules/meow": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cosmiconfig": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", @@ -1490,6 +1616,8 @@ "async-done": "^2.0.0", "chai": "^6.0.1", "concurrently": "^9.0.1", + "conventional-changelog-conventionalcommits": "^7.0.2", + "conventional-recommended-bump": "^11.2.0", "eslint": "^9.15.0", "eslint-config-google": "^0.14.0", "eslint-config-prettier": "^10.1.1", diff --git a/packages/blockly/package.json b/packages/blockly/package.json index 168d415b3..52d5085e2 100644 --- a/packages/blockly/package.json +++ b/packages/blockly/package.json @@ -111,6 +111,8 @@ "async-done": "^2.0.0", "chai": "^6.0.1", "concurrently": "^9.0.1", + "conventional-changelog-conventionalcommits": "^7.0.2", + "conventional-recommended-bump": "^11.2.0", "eslint": "^9.15.0", "eslint-config-google": "^0.14.0", "eslint-config-prettier": "^10.1.1", From de7abd0c40b6c5a47ba16cc2fc7bbb92e3fadb57 Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Mon, 16 Mar 2026 15:56:26 -0700 Subject: [PATCH 05/17] fix: Remove unsafe non-null assertions (#9598) --- packages/blockly/core/toolbox/toolbox.ts | 35 +++++++++++------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/packages/blockly/core/toolbox/toolbox.ts b/packages/blockly/core/toolbox/toolbox.ts index 6f4daf4ed..f58536257 100644 --- a/packages/blockly/core/toolbox/toolbox.ts +++ b/packages/blockly/core/toolbox/toolbox.ts @@ -11,7 +11,6 @@ */ // Former goog.module ID: Blockly.Toolbox -// Unused import preserved for side-effects. Remove if unneeded. import {BlockSvg} from '../block_svg.js'; import * as browserEvents from '../browser_events.js'; import * as common from '../common.js'; @@ -192,7 +191,7 @@ export class Toolbox aria.setRole(this.contentsDiv_, aria.Role.TREE); container.appendChild(this.contentsDiv_); - svg.parentNode!.insertBefore(container, svg); + svg.parentNode?.insertBefore(container, svg); this.attachEvents_(container, this.contentsDiv_); return container; @@ -281,7 +280,7 @@ export class Toolbox const itemId = (targetElement as Element).getAttribute('id'); if (itemId) { const item = this.getToolboxItemById(itemId); - if (item!.isSelectable()) { + if (item?.isSelectable()) { this.setSelectedItem(item); (item as ISelectableToolboxItem).onClick(e); } @@ -396,7 +395,7 @@ export class Toolbox const toolboxItemDef = toolboxDef[i]; this.createToolboxItem(toolboxItemDef, fragment); } - this.contentsDiv_!.appendChild(fragment); + this.contentsDiv_?.appendChild(fragment); } /** @@ -435,9 +434,7 @@ export class Toolbox } // Adds the ID to the HTML element that can receive a click. // This is used in onClick_ to find the toolboxItem that was clicked. - if (toolboxItem.getClickTarget()) { - toolboxItem.getClickTarget()!.setAttribute('id', toolboxItem.getId()); - } + toolboxItem.getClickTarget()?.setAttribute('id', toolboxItem.getId()); } } @@ -722,7 +719,7 @@ export class Toolbox this.width_ = toolboxDiv.offsetWidth; this.height_ = workspaceMetrics.viewHeight; } - this.flyout!.position(); + this.flyout?.position(); } /** @@ -731,10 +728,11 @@ export class Toolbox * @internal */ handleToolboxItemResize() { + if (!this.HtmlDiv) return; // Reposition the workspace so that (0,0) is in the correct position // relative to the new absolute edge (ie toolbox edge). const workspace = this.workspace_; - const rect = this.HtmlDiv!.getBoundingClientRect(); + const rect = this.HtmlDiv.getBoundingClientRect(); const flyout = this.getFlyout(); const newX = this.toolboxPosition === toolbox.Position.LEFT @@ -786,7 +784,7 @@ export class Toolbox this.selectedItem_.isSelectable() && this.selectedItem_.getContents().length ) { - this.flyout!.show(this.selectedItem_.getContents()); + this.flyout?.show(this.selectedItem_.getContents()); } } @@ -800,7 +798,9 @@ export class Toolbox return; } - this.HtmlDiv!.style.display = isVisible ? 'block' : 'none'; + if (this.HtmlDiv) { + this.HtmlDiv.style.display = isVisible ? 'block' : 'none'; + } this.isVisible_ = isVisible; // Invisible toolbox is ignored as drag targets and must have the drag // target updated. @@ -944,10 +944,10 @@ export class Toolbox (oldItem === newItem && !newItem.isCollapsible()) || !newItem.getContents().length ) { - this.flyout!.hide(); + this.flyout?.hide(); } else { - this.flyout!.show(newItem.getContents()); - this.flyout!.scrollToStart(); + this.flyout?.show(newItem.getContents()); + this.flyout?.scrollToStart(); } } @@ -992,10 +992,7 @@ export class Toolbox const collapsibleItem = this.selectedItem_ as ICollapsibleToolboxItem; collapsibleItem.toggleExpanded(); return true; - } else if ( - this.selectedItem_.getParent() && - this.selectedItem_.getParent()!.isSelectable() - ) { + } else if (this.selectedItem_.getParent()?.isSelectable()) { this.setSelectedItem(this.selectedItem_.getParent()); return true; } @@ -1075,7 +1072,7 @@ export class Toolbox /** Disposes of this toolbox. */ dispose() { this.workspace_.getComponentManager().removeComponent('toolbox'); - this.flyout!.dispose(); + this.flyout?.dispose(); this.contents.forEach((item) => item.dispose()); for (let j = 0; j < this.boundEvents_.length; j++) { From 6413d712578443832eb251c649594196c355b889 Mon Sep 17 00:00:00 2001 From: Maribeth Moffatt Date: Tue, 17 Mar 2026 11:22:43 -0400 Subject: [PATCH 06/17] chore: fix version command for publish (#9637) --- .github/workflows/publish.yml | 2 +- package-lock.json | 143 +++++++++------------------------- packages/blockly/package.json | 2 +- 3 files changed, 40 insertions(+), 107 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 194573bdd..fa275bb6a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -40,7 +40,7 @@ jobs: id: bump working-directory: packages/blockly run: | - RELEASE_TYPE=$(npx conventional-recommended-bump --preset conventionalcommits) + RELEASE_TYPE=$(npx conventional-recommended-bump --preset conventionalcommits -t blockly-) echo "release_type=$RELEASE_TYPE" >> "$GITHUB_OUTPUT" echo "Recommended bump: $RELEASE_TYPE" diff --git a/package-lock.json b/package-lock.json index 778b4aafc..ec0d731c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -298,62 +298,6 @@ "node": ">=v18" } }, - "node_modules/@conventional-changelog/git-client": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@conventional-changelog/git-client/-/git-client-2.6.0.tgz", - "integrity": "sha512-T+uPDciKf0/ioNNDpMGc8FDsehJClZP0yR3Q5MN6wE/Y/1QZ7F+80OgznnTCOlMEG4AV0LvH2UJi3C/nBnaBUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@simple-libs/child-process-utils": "^1.0.0", - "@simple-libs/stream-utils": "^1.2.0", - "semver": "^7.5.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "conventional-commits-filter": "^5.0.0", - "conventional-commits-parser": "^6.3.0" - }, - "peerDependenciesMeta": { - "conventional-commits-filter": { - "optional": true - }, - "conventional-commits-parser": { - "optional": true - } - } - }, - "node_modules/@simple-libs/child-process-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@simple-libs/child-process-utils/-/child-process-utils-1.0.2.tgz", - "integrity": "sha512-/4R8QKnd/8agJynkNdJmNw2MBxuFTRcNFnE5Sg/G+jkSsV8/UBgULMzhizWWW42p8L5H7flImV2ATi79Ove2Tw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@simple-libs/stream-utils": "^1.2.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://ko-fi.com/dangreen" - } - }, - "node_modules/@simple-libs/stream-utils": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@simple-libs/stream-utils/-/stream-utils-1.2.0.tgz", - "integrity": "sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://ko-fi.com/dangreen" - } - }, "node_modules/@types/conventional-commits-parser": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.2.tgz", @@ -571,23 +515,23 @@ } }, "node_modules/conventional-changelog-preset-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-5.0.0.tgz", - "integrity": "sha512-SetDSntXLk8Jh1NOAl1Gu5uLiCNSYenB5tm0YVeZKePRIgDW9lQImromTwLa3c/Gae298tsgOM+/CYT9XAl0NA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-4.1.0.tgz", + "integrity": "sha512-HozQjJicZTuRhCRTq4rZbefaiCzRM2pr6u2NL3XhrmQm4RMnDXfESU6JKu/pnKwx5xtdkYfNCsbhN5exhiKGJA==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=16" } }, "node_modules/conventional-commits-filter": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-5.0.0.tgz", - "integrity": "sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-4.0.0.tgz", + "integrity": "sha512-rnpnibcSOdFcdclpFwWa+pPlZJhXE7l+XK04zxhbWrhgpR96h33QLz8hITTXbcYICxVr3HZFtbtUAQ+4LdBo9A==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=16" } }, "node_modules/conventional-commits-parser": { @@ -610,53 +554,24 @@ } }, "node_modules/conventional-recommended-bump": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-11.2.0.tgz", - "integrity": "sha512-lqIdmw330QdMBgfL0e6+6q5OMKyIpy4OZNmepit6FS3GldhkG+70drZjuZ0A5NFpze5j85dlYs3GabQXl6sMHw==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-9.0.0.tgz", + "integrity": "sha512-HR1yD0G5HgYAu6K0wJjLd7QGRK8MQDqqj6Tn1n/ja1dFwBCE6QmV+iSgQ5F7hkx7OUR/8bHpxJqYtXj2f/opPQ==", "dev": true, "license": "MIT", "dependencies": { - "@conventional-changelog/git-client": "^2.5.1", - "conventional-changelog-preset-loader": "^5.0.0", - "conventional-commits-filter": "^5.0.0", - "conventional-commits-parser": "^6.1.0", - "meow": "^13.0.0" + "conventional-changelog-preset-loader": "^4.1.0", + "conventional-commits-filter": "^4.0.0", + "conventional-commits-parser": "^5.0.0", + "git-raw-commits": "^4.0.0", + "git-semver-tags": "^7.0.0", + "meow": "^12.0.1" }, "bin": { - "conventional-recommended-bump": "dist/cli/index.js" + "conventional-recommended-bump": "cli.mjs" }, "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-recommended-bump/node_modules/conventional-commits-parser": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-6.3.0.tgz", - "integrity": "sha512-RfOq/Cqy9xV9bOA8N+ZH6DlrDR+5S3Mi0B5kACEjESpE+AviIpAptx9a9cFpWCCvgRtWT+0BbUw+e1BZfts9jg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@simple-libs/stream-utils": "^1.2.0", - "meow": "^13.0.0" - }, - "bin": { - "conventional-commits-parser": "dist/cli/index.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-recommended-bump/node_modules/meow": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", - "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=16" } }, "node_modules/cosmiconfig": { @@ -854,6 +769,24 @@ "node": ">=16" } }, + "node_modules/git-semver-tags": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-7.0.1.tgz", + "integrity": "sha512-NY0ZHjJzyyNXHTDZmj+GG7PyuAKtMsyWSwh07CR2hOZFa+/yoTsXci/nF2obzL8UDhakFNkD9gNdt/Ed+cxh2Q==", + "deprecated": "This package is no longer maintained. For the JavaScript API, please use @conventional-changelog/git-client instead.", + "dev": true, + "license": "MIT", + "dependencies": { + "meow": "^12.0.1", + "semver": "^7.5.2" + }, + "bin": { + "git-semver-tags": "cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/global-directory": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", @@ -1617,7 +1550,7 @@ "chai": "^6.0.1", "concurrently": "^9.0.1", "conventional-changelog-conventionalcommits": "^7.0.2", - "conventional-recommended-bump": "^11.2.0", + "conventional-recommended-bump": "^9.0.0", "eslint": "^9.15.0", "eslint-config-google": "^0.14.0", "eslint-config-prettier": "^10.1.1", diff --git a/packages/blockly/package.json b/packages/blockly/package.json index 52d5085e2..7f0107241 100644 --- a/packages/blockly/package.json +++ b/packages/blockly/package.json @@ -112,7 +112,7 @@ "chai": "^6.0.1", "concurrently": "^9.0.1", "conventional-changelog-conventionalcommits": "^7.0.2", - "conventional-recommended-bump": "^11.2.0", + "conventional-recommended-bump": "^9.0.0", "eslint": "^9.15.0", "eslint-config-google": "^0.14.0", "eslint-config-prettier": "^10.1.1", From 5239bde02142d2911bab49984924d6d33173b341 Mon Sep 17 00:00:00 2001 From: Maribeth Moffatt Date: Wed, 18 Mar 2026 13:09:52 -0400 Subject: [PATCH 07/17] chore: add release env to publish action to get review (#9639) --- .github/workflows/publish.yml | 53 ++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index fa275bb6a..058e04c0a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -17,10 +17,12 @@ jobs: ci: uses: ./.github/workflows/build.yml - publish: + version: needs: ci runs-on: ubuntu-latest timeout-minutes: 30 + outputs: + version: ${{ steps.version.outputs.version }} steps: - name: Checkout uses: actions/checkout@v5 @@ -56,38 +58,69 @@ jobs: echo "version=$VERSION" >> "$GITHUB_OUTPUT" echo "New version: $VERSION" + - name: Update lockfile + run: npm install + + - name: Upload versioned files + uses: actions/upload-artifact@v4 + with: + name: versioned-files + path: | + packages/blockly/package.json + package-lock.json + + publish: + needs: version + runs-on: ubuntu-latest + if: ${{ !inputs.dry_run }} + environment: release + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Download versioned files + uses: actions/download-artifact@v4 + with: + name: versioned-files + - name: Commit and push version bump - if: ${{ !inputs.dry_run }} run: | git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git add packages/blockly/package.json package-lock.json - git commit -m "chore: release v${{ steps.version.outputs.version }}" + git commit -m "release: v${{ needs.version.outputs.version }}" git push + - name: Setup Node.js + uses: actions/setup-node@v5 + with: + node-version: 22.x + registry-url: 'https://registry.npmjs.org' + + - name: Install dependencies + run: npm ci + - name: Build package - if: ${{ !inputs.dry_run }} working-directory: packages/blockly run: npm run package - name: Publish to npm - if: ${{ !inputs.dry_run }} working-directory: packages/blockly/dist run: npm publish - name: Create tarball - if: ${{ !inputs.dry_run }} working-directory: packages/blockly run: npm pack ./dist - name: Create GitHub release - if: ${{ !inputs.dry_run }} working-directory: packages/blockly env: GH_TOKEN: ${{ github.token }} run: | - TARBALL=$(ls blockly-*.tgz) - gh release create "blockly-v${{ steps.version.outputs.version }}" "$TARBALL" \ + TARBALL="blockly-${{ needs.version.outputs.version }}.tgz" + gh release create "blockly-v${{ needs.version.outputs.version }}" "$TARBALL" \ --repo "$GITHUB_REPOSITORY" \ - --title "blockly-v${{ steps.version.outputs.version }}" \ + --title "blockly-v${{ needs.version.outputs.version }}" \ --generate-notes From 92c73f62c77880961d3ceda5262facebec6596ec Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Wed, 18 Mar 2026 10:10:37 -0700 Subject: [PATCH 08/17] fix: Fix bug that caused blocks to become disconnected when undoing deletions (#9636) --- packages/blockly/core/connection.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/blockly/core/connection.ts b/packages/blockly/core/connection.ts index a55c25059..a79b7b9b1 100644 --- a/packages/blockly/core/connection.ts +++ b/packages/blockly/core/connection.ts @@ -291,10 +291,7 @@ export class Connection { } let event; - if ( - eventUtils.isEnabled() && - !childConnection.getSourceBlock().isDeadOrDying() - ) { + if (eventUtils.isEnabled()) { event = new (eventUtils.get(EventType.BLOCK_MOVE))( childConnection.getSourceBlock(), ) as BlockMove; From d1bbc97c537514dde547553761ac7fd103152ceb Mon Sep 17 00:00:00 2001 From: Maribeth Moffatt Date: Thu, 19 Mar 2026 12:49:35 -0400 Subject: [PATCH 09/17] chore: add a deploy key to allow pushing to main (#9642) --- .github/workflows/publish.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 058e04c0a..6ad69e0f8 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -79,6 +79,7 @@ jobs: uses: actions/checkout@v5 with: fetch-depth: 0 + ssh-key: ${{ secrets.DEPLOY_PRIVATE_KEY }} - name: Download versioned files uses: actions/download-artifact@v4 From ec6035e80923b18ea7fca63dc3ca2e2077c18e5e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 19 Mar 2026 17:00:15 +0000 Subject: [PATCH 10/17] release: v12.5.0 --- package-lock.json | 2 +- packages/blockly/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index ec0d731c0..7d196832c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1530,7 +1530,7 @@ } }, "packages/blockly": { - "version": "12.4.1", + "version": "12.5.0", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { diff --git a/packages/blockly/package.json b/packages/blockly/package.json index 7f0107241..480db088b 100644 --- a/packages/blockly/package.json +++ b/packages/blockly/package.json @@ -1,6 +1,6 @@ { "name": "blockly", - "version": "12.4.1", + "version": "12.5.0", "description": "Blockly is a library for building visual programming editors.", "keywords": [ "blockly" From 48426dc4858bbea211289c2a7d1e36ca9cae481e Mon Sep 17 00:00:00 2001 From: Maribeth Moffatt Date: Thu, 19 Mar 2026 13:57:36 -0400 Subject: [PATCH 11/17] chore: add option to publish the package without bumping version (#9643) --- .github/workflows/publish.yml | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 6ad69e0f8..b0c6344a5 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -4,7 +4,14 @@ on: workflow_dispatch: inputs: dry_run: - description: 'Dry run' + description: 'Dry run - print the version that would be published, but do not commit or publish anything.' + required: false + default: false + type: boolean + skip_versioning: + description: > + Skip version bump - use the version already in the repo + (e.g. retry after npm publish failed but the release commit is already pushed). required: false default: false type: boolean @@ -36,10 +43,12 @@ jobs: registry-url: 'https://registry.npmjs.org' - name: Install dependencies + if: ${{ !inputs.skip_versioning }} run: npm ci - name: Determine version bump id: bump + if: ${{ !inputs.skip_versioning }} working-directory: packages/blockly run: | RELEASE_TYPE=$(npx conventional-recommended-bump --preset conventionalcommits -t blockly-) @@ -47,21 +56,20 @@ jobs: echo "Recommended bump: $RELEASE_TYPE" - name: Apply version bump + if: ${{ !inputs.skip_versioning }} working-directory: packages/blockly run: npm version ${{ steps.bump.outputs.release_type }} --no-git-tag-version - - name: Read new version + - name: Read package version id: version working-directory: packages/blockly run: | VERSION=$(node -p "require('./package.json').version") echo "version=$VERSION" >> "$GITHUB_OUTPUT" - echo "New version: $VERSION" - - - name: Update lockfile - run: npm install + echo "Version: $VERSION" - name: Upload versioned files + if: ${{ !inputs.skip_versioning }} uses: actions/upload-artifact@v4 with: name: versioned-files @@ -82,11 +90,13 @@ jobs: ssh-key: ${{ secrets.DEPLOY_PRIVATE_KEY }} - name: Download versioned files + if: ${{ !inputs.skip_versioning }} uses: actions/download-artifact@v4 with: name: versioned-files - name: Commit and push version bump + if: ${{ !inputs.skip_versioning }} run: | git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" @@ -109,7 +119,7 @@ jobs: - name: Publish to npm working-directory: packages/blockly/dist - run: npm publish + run: npm publish --verbose - name: Create tarball working-directory: packages/blockly From 46d7294dcab2954ad1bdc5fb0229b124b4baea67 Mon Sep 17 00:00:00 2001 From: Maribeth Moffatt Date: Thu, 19 Mar 2026 14:17:17 -0400 Subject: [PATCH 12/17] chore: use node 24 for publishing (#9644) --- .github/workflows/publish.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b0c6344a5..0f403f447 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -39,7 +39,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v5 with: - node-version: 22.x + node-version: 24.x registry-url: 'https://registry.npmjs.org' - name: Install dependencies @@ -107,7 +107,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v5 with: - node-version: 22.x + node-version: 24.x registry-url: 'https://registry.npmjs.org' - name: Install dependencies From 92dd086b3ae37356d6fad50aaa7b21fe6da7d19d Mon Sep 17 00:00:00 2001 From: Maribeth Moffatt Date: Thu, 19 Mar 2026 14:39:30 -0400 Subject: [PATCH 13/17] chore: update repo name in blockly package (#9645) --- packages/blockly/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/blockly/package.json b/packages/blockly/package.json index 480db088b..84dac551e 100644 --- a/packages/blockly/package.json +++ b/packages/blockly/package.json @@ -7,10 +7,10 @@ ], "repository": { "type": "git", - "url": "git+https://github.com/google/blockly.git" + "url": "git+https://github.com/RaspberryPiFoundation/blockly.git" }, "bugs": { - "url": "https://github.com/google/blockly/issues" + "url": "https://github.com/RaspberryPiFoundation/blockly/issues" }, "homepage": "https://developers.google.com/blockly/", "author": { From 1f1e2c4679fb32e82f9fef5d2e413767103ee707 Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Fri, 20 Mar 2026 09:38:55 -0700 Subject: [PATCH 14/17] Revert "fix: Improve zoom animations (#9584)" (#9647) This reverts commit 3acdf5e536b5c1263cc3ac1005091b70c485eafd. --- packages/blockly/core/css.ts | 9 +-------- packages/blockly/core/layer_manager.ts | 14 ++++++-------- packages/blockly/core/zoom_controls.ts | 4 +--- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/packages/blockly/core/css.ts b/packages/blockly/core/css.ts index c29f9f97c..60ad86049 100644 --- a/packages/blockly/core/css.ts +++ b/packages/blockly/core/css.ts @@ -84,14 +84,7 @@ let content = ` .blocklyBlockCanvas.blocklyCanvasTransitioning, .blocklyBubbleCanvas.blocklyCanvasTransitioning { - transition: transform .15s; -} - -@media (prefers-reduced-motion) { - .blocklyBlockCanvas.blocklyCanvasTransitioning, - .blocklyBubbleCanvas.blocklyCanvasTransitioning { - transition: none; - } + transition: transform .5s; } .blocklyEmboss { diff --git a/packages/blockly/core/layer_manager.ts b/packages/blockly/core/layer_manager.ts index 7d253b110..1142bcf58 100644 --- a/packages/blockly/core/layer_manager.ts +++ b/packages/blockly/core/layer_manager.ts @@ -73,11 +73,11 @@ export class LayerManager { * @internal */ appendToAnimationLayer(elem: IRenderedElement) { - const currentTransform = this.dragLayer?.style.transform; + const currentTransform = this.dragLayer?.getAttribute('transform'); // Only update the current transform when appending, so animations don't // move if the workspace moves. - if (currentTransform && this.animationLayer) { - this.animationLayer.style.transform = currentTransform; + if (currentTransform) { + this.animationLayer?.setAttribute('transform', currentTransform); } this.animationLayer?.appendChild(elem.getSvgRoot()); } @@ -88,12 +88,10 @@ export class LayerManager { * @internal */ translateLayers(newCoord: Coordinate, newScale: number) { - const translation = `translate(${newCoord.x}px, ${newCoord.y}px) scale(${newScale})`; - if (this.dragLayer) { - this.dragLayer.style.transform = translation; - } + const translation = `translate(${newCoord.x}, ${newCoord.y}) scale(${newScale})`; + this.dragLayer?.setAttribute('transform', translation); for (const [_, layer] of this.layers) { - layer.style.transform = translation; + layer.setAttribute('transform', translation); } } diff --git a/packages/blockly/core/zoom_controls.ts b/packages/blockly/core/zoom_controls.ts index 6bd119423..4f14b73be 100644 --- a/packages/blockly/core/zoom_controls.ts +++ b/packages/blockly/core/zoom_controls.ts @@ -373,10 +373,8 @@ export class ZoomControls implements IPositionable { * @param e A mouse down event. */ private zoom(amount: number, e: PointerEvent) { - this.workspace.beginCanvasTransition(); this.workspace.markFocused(); this.workspace.zoomCenter(amount); - setTimeout(this.workspace.endCanvasTransition.bind(this.workspace), 150); this.fireZoomEvent(); Touch.clearTouchIdentifier(); // Don't block future drags. e.stopPropagation(); // Don't start a workspace scroll. @@ -461,7 +459,7 @@ export class ZoomControls implements IPositionable { this.workspace.zoomCenter(amount); this.workspace.scrollCenter(); - setTimeout(this.workspace.endCanvasTransition.bind(this.workspace), 150); + setTimeout(this.workspace.endCanvasTransition.bind(this.workspace), 500); this.fireZoomEvent(); Touch.clearTouchIdentifier(); // Don't block future drags. e.stopPropagation(); // Don't start a workspace scroll. From 6f7d50552ee658299de16c139673c2d126ac9b16 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 17:04:50 +0000 Subject: [PATCH 15/17] release: v12.5.1 --- package-lock.json | 2 +- packages/blockly/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7d196832c..42be06f1a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1530,7 +1530,7 @@ } }, "packages/blockly": { - "version": "12.5.0", + "version": "12.5.1", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { diff --git a/packages/blockly/package.json b/packages/blockly/package.json index 84dac551e..ed7562715 100644 --- a/packages/blockly/package.json +++ b/packages/blockly/package.json @@ -1,6 +1,6 @@ { "name": "blockly", - "version": "12.5.0", + "version": "12.5.1", "description": "Blockly is a library for building visual programming editors.", "keywords": [ "blockly" From 5dedd858725c5925b13278a278783fad7c958a6d Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Wed, 25 Mar 2026 15:30:40 +0000 Subject: [PATCH 16/17] chore: remove unused gulp helpers (#9651) * chore: remove unused dev dependency gulp-insert * chore: remove unused dev dependency gulp-series * chore: remove unused dev dependency gulp-shell --- package-lock.json | 111 ---------------------------------- packages/blockly/package.json | 3 - 2 files changed, 114 deletions(-) diff --git a/package-lock.json b/package-lock.json index 42be06f1a..6d53d3e19 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1564,11 +1564,8 @@ "gulp-concat": "^2.6.1", "gulp-gzip": "^1.4.2", "gulp-header": "^2.0.9", - "gulp-insert": "^0.5.0", "gulp-rename": "^2.0.0", "gulp-replace": "^1.0.0", - "gulp-series": "^1.0.2", - "gulp-shell": "^0.8.0", "gulp-sourcemaps": "^3.0.0", "gulp-umd": "^2.0.0", "http-server": "^14.0.0", @@ -6254,36 +6251,6 @@ "xtend": "~4.0.1" } }, - "packages/blockly/node_modules/gulp-insert": { - "version": "0.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "^1.0.26-4", - "streamqueue": "0.0.6" - } - }, - "packages/blockly/node_modules/gulp-insert/node_modules/isarray": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "packages/blockly/node_modules/gulp-insert/node_modules/readable-stream": { - "version": "1.1.14", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "packages/blockly/node_modules/gulp-insert/node_modules/string_decoder": { - "version": "0.10.31", - "dev": true, - "license": "MIT" - }, "packages/blockly/node_modules/gulp-rename": { "version": "2.1.0", "dev": true, @@ -6307,48 +6274,6 @@ "node": ">=10" } }, - "packages/blockly/node_modules/gulp-series": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "packages/blockly/node_modules/gulp-shell": { - "version": "0.8.0", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^3.0.0", - "fancy-log": "^1.3.3", - "lodash.template": "^4.5.0", - "plugin-error": "^1.0.1", - "through2": "^3.0.1", - "tslib": "^1.10.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "packages/blockly/node_modules/gulp-shell/node_modules/chalk": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "packages/blockly/node_modules/gulp-shell/node_modules/through2": { - "version": "3.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - }, "packages/blockly/node_modules/gulp-sourcemaps": { "version": "3.0.0", "dev": true, @@ -8996,37 +8921,6 @@ "any-promise": "^1.1.0" } }, - "packages/blockly/node_modules/streamqueue": { - "version": "0.0.6", - "dev": true, - "dependencies": { - "readable-stream": "^1.0.26-2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "packages/blockly/node_modules/streamqueue/node_modules/isarray": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "packages/blockly/node_modules/streamqueue/node_modules/readable-stream": { - "version": "1.1.14", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "packages/blockly/node_modules/streamqueue/node_modules/string_decoder": { - "version": "0.10.31", - "dev": true, - "license": "MIT" - }, "packages/blockly/node_modules/string_decoder": { "version": "1.1.1", "dev": true, @@ -9298,11 +9192,6 @@ "typescript": ">=4.8.4" } }, - "packages/blockly/node_modules/tslib": { - "version": "1.14.1", - "dev": true, - "license": "0BSD" - }, "packages/blockly/node_modules/type": { "version": "1.2.0", "dev": true, diff --git a/packages/blockly/package.json b/packages/blockly/package.json index ed7562715..623e967a3 100644 --- a/packages/blockly/package.json +++ b/packages/blockly/package.json @@ -126,11 +126,8 @@ "gulp-concat": "^2.6.1", "gulp-gzip": "^1.4.2", "gulp-header": "^2.0.9", - "gulp-insert": "^0.5.0", "gulp-rename": "^2.0.0", "gulp-replace": "^1.0.0", - "gulp-series": "^1.0.2", - "gulp-shell": "^0.8.0", "gulp-sourcemaps": "^3.0.0", "gulp-umd": "^2.0.0", "http-server": "^14.0.0", From f454e1b3174c72e34a73664f92928e37c6b2066a Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Wed, 1 Apr 2026 12:49:20 -0700 Subject: [PATCH 17/17] chore: Bump closure to the latest version --- package-lock.json | 68 ++++++++++++++++++++++++++++++----- packages/blockly/package.json | 2 +- 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 58d982a5c..0a4f05b47 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1093,12 +1093,14 @@ } }, "node_modules/google-closure-compiler": { - "version": "20260315.0.0", + "version": "20260330.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20260330.0.0.tgz", + "integrity": "sha512-USY3fekBavIfAkzHEooo6FcuTT/+z6FbfMRK3l3nsgsKB2oJ4baPPz2XYGSivHNstB8l10CcPvWh5FwlWZpzvQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "chalk": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 <5.6.1 || ^5.6.2 >5.6.1", - "google-closure-compiler-java": "^20260315.0.0", + "google-closure-compiler-java": "^20260330.0.0", "minimist": "^1.0.0", "vinyl": "^3.0.1", "vinyl-sourcemaps-apply": "^0.2.0" @@ -1110,19 +1112,52 @@ "node": ">=18" }, "optionalDependencies": { - "google-closure-compiler-linux": "^20260315.0.0", - "google-closure-compiler-linux-arm64": "^20260315.0.0", - "google-closure-compiler-macos": "^20260315.0.0", - "google-closure-compiler-windows": "^20260315.0.0" + "google-closure-compiler-linux": "^20260330.0.0", + "google-closure-compiler-linux-arm64": "^20260330.0.0", + "google-closure-compiler-macos": "^20260330.0.0", + "google-closure-compiler-windows": "^20260330.0.0" } }, "node_modules/google-closure-compiler-java": { - "version": "20260315.0.0", + "version": "20260330.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20260330.0.0.tgz", + "integrity": "sha512-wc+HpQlNvS5mquzVjpOjhVlgYgvxnOyqPDCJJN2k7+5dVE7mbzZya7mIEfsPaRZ39KbPVvNrDpMEAahKiuNtjA==", "dev": true, "license": "Apache-2.0" }, + "node_modules/google-closure-compiler-linux": { + "version": "20260330.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20260330.0.0.tgz", + "integrity": "sha512-BWEknhsCj/zero4Zk0/FtbAM1eO3QQA34xGQa4HeREV36trs/zmVCSVRqYCYcEAAEBiMjj97wMPdhFSkm72k8g==", + "cpu": [ + "x32", + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/google-closure-compiler-linux-arm64": { + "version": "20260330.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-linux-arm64/-/google-closure-compiler-linux-arm64-20260330.0.0.tgz", + "integrity": "sha512-7C9khLgtZEUfZ/xCkjLVTC5vRJt5CmfWwiAk/u3+pPzsDubngHwKE1e0UTPqNwJEXo8VVXM4OdvrY7hzwR4MZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/google-closure-compiler-macos": { - "version": "20260315.0.0", + "version": "20260330.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-macos/-/google-closure-compiler-macos-20260330.0.0.tgz", + "integrity": "sha512-3mGI7eYwIZYAZFdMwpS4wXB5+q/kKbl936FtvRIIgRtFhSX7m6kwsyXqGP62ZvuOCcPcW14dC6k7g6l7eS2Fgw==", "cpu": [ "arm64" ], @@ -1133,6 +1168,21 @@ "darwin" ] }, + "node_modules/google-closure-compiler-windows": { + "version": "20260330.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20260330.0.0.tgz", + "integrity": "sha512-dqMKvjzdAlgERhHKHG12dKrOcL2ASNeKP1c3doCQn3vwZizz1xV2Ns6m711tb6pfNXFstfR6VJAoMuv/BjmdYQ==", + "cpu": [ + "x32", + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/http-proxy-agent": { "version": "7.0.2", "dev": true, @@ -1925,7 +1975,7 @@ "eslint-plugin-prettier": "^5.2.1", "glob": "^11.0.1", "globals": "^16.0.0", - "google-closure-compiler": "^20260315.0.0", + "google-closure-compiler": "^20260330.0.0", "gulp": "^5.0.0", "gulp-concat": "^2.6.1", "gulp-gzip": "^1.4.2", diff --git a/packages/blockly/package.json b/packages/blockly/package.json index 89c46f3ba..7f6d53970 100644 --- a/packages/blockly/package.json +++ b/packages/blockly/package.json @@ -123,7 +123,7 @@ "eslint-plugin-prettier": "^5.2.1", "glob": "^11.0.1", "globals": "^16.0.0", - "google-closure-compiler": "^20260315.0.0", + "google-closure-compiler": "^20260330.0.0", "gulp": "^5.0.0", "gulp-concat": "^2.6.1", "gulp-gzip": "^1.4.2",