Phase 4: CI, lint and publishing automation#20
Conversation
- 4.1 Remove the dead Jenkinsfile (pinned to node:6.6.0). (.travis.yml was already removed in Phase 1.) - 4.2 Add a GitHub Actions build workflow: on every PR/push it runs npm ci, lint, tests and a full package, and uploads the .vsix artifact. This is the check that would have caught the Dependabot gulp4/webpack5 breakage. - 4.3 Add a tag-triggered publish workflow (tfx extension publish). Requires a maintainer to add the AZURE_DEVOPS_MARKETPLACE_PAT secret; documented in the workflow, with a note to move to Entra/OIDC before all-org PATs retire 2026-12-01. - 4.4 Fix the CodeQL workflow: github/codeql-action/*@V3 + actions/checkout@v4 (the @v1 actions were disabled by GitHub in Jan 2023, so the repo's only scan produced no signal), language javascript-typescript. - 4.5 Replace the babel-eslint .eslintrc with an ESLint 9 flat config (eslint.config.mjs): typescript-eslint for the .ts tasks, node config for the build scripts, a lenient config for the legacy tab scripts. Wire `npm run lint`; strip the deprecated /* eslint-env */ comments from the tab scripts. - 4.6 README: pipeline-usage quick-start (service connection + TBMain/TBStopTunnel YAML) and a Development/CI section; note compile step in the package pipeline. Verified locally: npm run lint (0 errors), npm test (8 passing), npm run package (builds the vsix); all three workflow YAMLs parse.
📝 WalkthroughWalkthroughThe change replaces legacy lint configuration with ESLint flat config, adds linting and Node 20 GitHub Actions build automation, modernizes CodeQL, introduces tag-based Marketplace publishing, and updates development and pipeline documentation. ChangesCI and tooling modernization
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant GitHubActions as GitHub Actions
participant Npm as npm
participant Marketplace as Visual Studio Marketplace
GitHubActions->>Npm: Run npm ci
GitHubActions->>Npm: Run npm run package
Npm-->>GitHubActions: Produce Packages/*.vsix
GitHubActions->>Marketplace: Publish VSIX with marketplace PAT
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/build.yml (1)
1-41: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winAdd concurrency control to cancel superseded PR builds.
Without a
concurrencyblock, every push to a PR branch creates a new workflow run that runs to completion even if newer commits arrive. Adding a concurrency group cancels obsolete runs and saves CI minutes.♻️ Suggested concurrency block
on: push: branches: [ master ] pull_request: branches: [ master ] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + permissions: contents: read🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/build.yml around lines 1 - 41, Add a workflow-level concurrency configuration near the top-level metadata in the Build workflow, using a group keyed to the workflow and ref so runs for the same PR or branch share a group, and enable cancellation of in-progress runs. Leave the existing build jobs and steps unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/publish.yml:
- Line 26: Configure every actions/checkout@v4 step with persist-credentials:
false: update .github/workflows/publish.yml at lines 26-26,
.github/workflows/build.yml at lines 16-16, and
.github/workflows/codeql-analysis.yml at lines 27-27. No other workflow changes
are required.
In `@CLAUDE.md`:
- Around line 43-44: Update the CI descriptions in CLAUDE.md lines 43-44 and
README.md lines 67-68 to state that lint, tests, and the full package build run
on every PR targeting master, matching the workflow trigger; do not broaden the
workflow scope.
In `@MODERNIZATION.md`:
- Around line 23-28: Synchronize the Phase 4 status across MODERNIZATION.md:
update the executive summary entry that says real CI/CD is “PENDING — Phase 4”
and the roadmap entry that presents the ESLint refresh as future work so they
reflect the completed or mostly completed work described in the Phase 4 section.
Alternatively, if those items are not complete, change the Phase 4
heading/status to remain pending.
In `@package.json`:
- Line 9: Add an engines.node constraint in package.json requiring Node.js
version 20 or newer, while preserving the existing lint script and other package
metadata.
In `@README.md`:
- Around line 23-24: Update the TBStopTunnel@0 cleanup task in the README
example to include condition: always(), ensuring the tunnel is stopped even when
earlier test steps fail.
---
Outside diff comments:
In @.github/workflows/build.yml:
- Around line 1-41: Add a workflow-level concurrency configuration near the
top-level metadata in the Build workflow, using a group keyed to the workflow
and ref so runs for the same PR or branch share a group, and enable cancellation
of in-progress runs. Leave the existing build jobs and steps unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: c255b330-e5f9-4ec6-baa9-2862f8af2815
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsontb-main/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (12)
.eslintrc.github/workflows/build.yml.github/workflows/codeql-analysis.yml.github/workflows/publish.ymlCLAUDE.mdJenkinsfileMODERNIZATION.mdREADME.mdeslint.config.mjspackage.jsontb-build-info/scripts/dialog.jstb-build-info/scripts/info.js
💤 Files with no reviewable changes (4)
- Jenkinsfile
- .eslintrc
- tb-build-info/scripts/info.js
- tb-build-info/scripts/dialog.js
| runs-on: ubuntu-latest | ||
| environment: marketplace | ||
| steps: | ||
| - uses: actions/checkout@v4 |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Set persist-credentials: false on all checkout steps. actions/checkout@v4 persists the GITHUB_TOKEN in .git/config by default. None of these workflows need git credentials after checkout, and leaving the token persisted expands the attack surface if a later step is compromised.
.github/workflows/publish.yml#L26: Addpersist-credentials: false— most critical since this workflow handles a Marketplace PAT..github/workflows/build.yml#L16: Addpersist-credentials: false..github/workflows/codeql-analysis.yml#L27: Addpersist-credentials: false.
🧰 Tools
🪛 zizmor (1.26.1)
[warning] 26-26: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 26-26: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
📍 Affects 3 files
.github/workflows/publish.yml#L26-L26(this comment).github/workflows/build.yml#L16-L16.github/workflows/codeql-analysis.yml#L27-L27
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/publish.yml at line 26, Configure every
actions/checkout@v4 step with persist-credentials: false: update
.github/workflows/publish.yml at lines 26-26, .github/workflows/build.yml at
lines 16-16, and .github/workflows/codeql-analysis.yml at lines 27-27. No other
workflow changes are required.
- Set persist-credentials: false on every actions/checkout step (build/publish/codeql) so the GITHUB_TOKEN is not left in .git/config. - Add engines.node >=20 to the root package.json (matches CI/runtime). - README: add condition: always() to the TBStopTunnel example so a failed test step still tears the tunnel down (default succeeded() would skip it). - Docs: say CI runs "on every PR targeting master" (CLAUDE.md, README) to match the workflow trigger; mark the Phase 4 CI/CD and ESLint items DONE in MODERNIZATION.md's top-5 actions and roadmap table.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@MODERNIZATION.md`:
- Line 48: Update the Phase 4 CI/CD entry in MODERNIZATION.md to accurately
state that Marketplace publishing currently uses the
AZURE_DEVOPS_MARKETPLACE_PAT with tfx extension publish, while Entra/OIDC
authentication remains a future migration. Preserve the existing
completed-status context.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 47ba735c-6491-4a5c-b7e8-c9264e41e101
📒 Files selected for processing (7)
.github/workflows/build.yml.github/workflows/codeql-analysis.yml.github/workflows/publish.ymlCLAUDE.mdMODERNIZATION.mdREADME.mdpackage.json
| 3. **Replace the broken gulp 3 / webpack 1 / babel 6 toolchain** with TypeScript + webpack 5 + npm scripts (per `microsoft/azure-devops-extension-sample`) so a `.vsix` can be built at all. _(DONE — Phase 1 build, Phase 2 TypeScript.)_ | ||
| 4. **Stop bundling the 2019 tunnel jar** (`tb-main/tunnel/2.30.jar`, internally v2.9, vulnerable Jetty 9.4.12) — use `testingbot-tunnel-launcher` (npm, v1.1.18) to download/cache the current tunnel (v4.8) at runtime. _(DONE — Phase 2.)_ | ||
| 5. **Add real CI/CD** — GitHub Actions building the `.vsix` on every PR and publishing to the Marketplace on tag (tfx-cli 0.23.x, Entra/OIDC auth), replacing dead Travis/Jenkins/CodeQL v1 configs. _(PENDING — Phase 4.)_ | ||
| 5. **Add real CI/CD** — GitHub Actions building the `.vsix` on every PR and publishing to the Marketplace on tag (tfx-cli 0.23.x, Entra/OIDC auth), replacing dead Travis/Jenkins/CodeQL v1 configs. _(DONE — Phase 4; the build/CodeQL/lint workflows run, the tag publish workflow just needs the maintainer's Marketplace secret.)_ |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Document the implemented PAT authentication accurately.
The publish workflow currently passes AZURE_DEVOPS_MARKETPLACE_PAT to tfx extension publish in .github/workflows/publish.yml Lines 41-44; Entra/OIDC is a future migration, not the implemented authentication path. Update this entry to say PAT-based publishing is implemented and OIDC remains pending.
Proposed fix
-5. **Add real CI/CD** — GitHub Actions building the `.vsix` on every PR and publishing to the Marketplace on tag (tfx-cli 0.23.x, Entra/OIDC auth), replacing dead Travis/Jenkins/CodeQL v1 configs.
+5. **Add real CI/CD** — GitHub Actions building the `.vsix` on every PR and publishing to the Marketplace on tag (tfx-cli 0.23.x, PAT auth for now; Entra/OIDC migration pending), replacing dead Travis/Jenkins/CodeQL v1 configs.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 5. **Add real CI/CD** — GitHub Actions building the `.vsix` on every PR and publishing to the Marketplace on tag (tfx-cli 0.23.x, Entra/OIDC auth), replacing dead Travis/Jenkins/CodeQL v1 configs. _(DONE — Phase 4; the build/CodeQL/lint workflows run, the tag publish workflow just needs the maintainer's Marketplace secret.)_ | |
| 5. **Add real CI/CD** — GitHub Actions building the `.vsix` on every PR and publishing to the Marketplace on tag (tfx-cli 0.23.x, PAT auth for now; Entra/OIDC migration pending), replacing dead Travis/Jenkins/CodeQL v1 configs. _(DONE — Phase 4; the build/CodeQL/lint workflows run, the tag publish workflow just needs the maintainer's Marketplace secret.)_ |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@MODERNIZATION.md` at line 48, Update the Phase 4 CI/CD entry in
MODERNIZATION.md to accurately state that Marketplace publishing currently uses
the AZURE_DEVOPS_MARKETPLACE_PAT with tfx extension publish, while Entra/OIDC
authentication remains a future migration. Preserve the existing
completed-status context.
Final phase of
MODERNIZATION.md: real CI/CD, linting, and a working CodeQL scan.What changed
Jenkinsfile(pinned tonode:6.6.0, which can't install the current toolchain)..travis.ymlwas already gone since Phase 1..github/workflows/build.yml: on every PR/push,npm ci→ lint → test → package → upload the.vsixartifact. This is exactly the check that would have caught the Dependabot gulp4/webpack5 breakage that shipped unnoticed..github/workflows/publish.yml: tag-triggered (v*) Marketplace publish viatfx extension publish. Needs a maintainer to add theAZURE_DEVOPS_MARKETPLACE_PATsecret; documented inline, with a note to move to Entra/OIDC before all-org PATs retire 2026-12-01.github/codeql-action/*@v3+actions/checkout@v4(the@v1actions were disabled by GitHub in Jan 2023, so the repo's only scan produced no signal), languagejavascript-typescript.babel-eslint.eslintrcwith an ESLint 9 flat config (eslint.config.mjs): typescript-eslint for the.tstasks, a node config for the build scripts, and a lenient config for the legacy tab scripts (slated for the SDK rewrite). Wirednpm run lintand stripped the deprecated/* eslint-env */comments.TBMain/TBStopTunnelYAML) and a Development/CI section.Verification
npm run lint→ 0 errors,npm test→ 8 passing,npm run package→ builds the vsix. All three workflow YAMLs parse. The build workflow will run on this PR itself.Follow-up for a maintainer
The publish workflow can't run until the
AZURE_DEVOPS_MARKETPLACE_PATsecret is added (and versions bumped inpackage.jsonbefore tagging). Everything else runs automatically.This completes the modernization roadmap. Remaining deferred/blocked items (tracked in
MODERNIZATION.md): theazure-devops-extension-sdk/ React tab port, and moving the/minisecret out of the browser (blocked on a TestingBot API endpoint).Summary by CodeRabbit
New Features
Documentation
Chores