mirror of
https://github.com/bitwarden/browser
synced 2025-12-06 00:13:28 +00:00
ci: add SDK breaking change detection workflow (#17075)
* ci: add SDK breaking change detection workflow
Introduces GitHub Actions workflow that detects TypeScript breaking changes when SDK artifacts are updated. Workflow is triggered via repository_dispatch from SDK repository and runs npm test:types with newly built SDK artifacts.
The workflow downloads SDK build artifacts, installs them locally, and executes the existing TypeScript type checking process. Exit codes determine success/failure for SDK repository monitoring via gh run watch.
Addresses issue where breaking changes in SDK are discovered only when clients attempt SDK version updates, rather than during SDK development.
* review: add input validation for client payload fields
Add validation step early in the workflow to check for required
client_payload fields and prevent failures from malformed payloads.
This improvement was requested during code review to provide better
error handling and debugging information when the SDK workflow sends
incomplete data.
Validates SOURCE_REPO, SDK_VERSION, ARTIFACTS_RUN_ID, and ARTIFACT_NAME
before proceeding with artifact download and type checking.
* review: update action versions to match repository standards
Update GitHub Actions to consistent versions used across the clients
repository for better security and compatibility. This change was
requested during code review to align with existing patterns.
- actions/checkout: v4.2.2 → v5.0.0 with specific SHA hash
- actions/setup-node: v4.2.0 → v5.0.0 with specific SHA hash
- actions/create-github-app-token: v2.1.1 → v2.0.3 with specific SHA hash
Uses specific SHA hashes for all actions following repository security standards.
* review: add timeout to type checking command for faster failure detection
Wrap npm run test:types with 10-minute timeout to provide faster feedback
when type checking hangs and more predictable workflow behavior. This
improvement was requested during code review to prevent workflows from
running until the 15-minute job timeout.
Provides clearer indication when type checking itself fails versus other
workflow issues, improving debugging experience for developers.
* review: use CLIENT_LABEL environment variable in logging and output
Add CLIENT_LABEL to log messages and GitHub Step Summary output for
better traceability and debugging. This change
was requested during
code review to make use of the defined CLIENT_LABEL environment
variable that was previously unused.
Improves workflow output clarity by showing which client type
(typescript, mobile, etc.) is being processed.
* review: add retry logic for npm ci command to handle network issues
Implement shell-based retry logic (3 attempts with 5-second delays) for
npm ci command to handle temporary network issues without adding external
dependencies. This improvement was requested during code review to make
the workflow more resilient to transient failures.
Continues with existing npm install approach while adding robustness
for dependency installation in GitHub Actions environment.
* review: improve shell script variable quoting for better practices
Update shell script to use proper variable quoting syntax throughout
(${VARIABLE} instead of $VARIABLE) for better shell scripting practices
and consistency. This change was requested during code review to follow
shell scripting best practices.
While this won't cause problems in practice, it prevents potential
word splitting issues and improves code maintainability.
* review: add back logging out of Azure
* review: adjust logic of retries for npm ci
* review: quote some strings
* review: add error catching around npm i
* review: remove unnecessary cleanup step
* review: use npm link and bitwarden/gh-actions/download-artifacts
* review: add underscores to job level env vars
* 🎨 fix artipacked zizmor issue and improved actionlint formatting
---------
Co-authored-by: Matt Andreko <mandreko@bitwarden.com>
This commit is contained in:
167
.github/workflows/sdk-breaking-change-check.yml
vendored
Normal file
167
.github/workflows/sdk-breaking-change-check.yml
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
# This workflow runs TypeScript compatibility checks when the SDK is updated.
|
||||
# Triggered automatically by the SDK repository via repository_dispatch when SDK PRs are created/updated.
|
||||
name: SDK Breaking Change Check
|
||||
run-name: "SDK breaking change check (${{ github.event.client_payload.sdk_version }})"
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [sdk-breaking-change-check]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
type-check:
|
||||
name: TypeScript compatibility check
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 15
|
||||
env:
|
||||
_SOURCE_REPO: ${{ github.event.client_payload.source_repo }}
|
||||
_SDK_VERSION: ${{ github.event.client_payload.sdk_version }}
|
||||
_ARTIFACTS_RUN_ID: ${{ github.event.client_payload.artifacts_info.run_id }}
|
||||
_ARTIFACT_NAME: ${{ github.event.client_payload.artifacts_info.artifact_name }}
|
||||
_CLIENT_LABEL: ${{ github.event.client_payload.client_label }}
|
||||
|
||||
steps:
|
||||
- name: Log in to Azure
|
||||
uses: bitwarden/gh-actions/azure-login@main
|
||||
with:
|
||||
subscription_id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
||||
tenant_id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
client_id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
- name: Get Azure Key Vault secrets
|
||||
id: get-kv-secrets
|
||||
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
||||
with:
|
||||
keyvault: gh-org-bitwarden
|
||||
secrets: "BW-GHAPP-ID,BW-GHAPP-KEY"
|
||||
|
||||
- name: Generate GH App token
|
||||
uses: actions/create-github-app-token@30bf6253fa41bdc8d1501d202ad15287582246b4 # v2.0.3
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ steps.get-kv-secrets.outputs.BW-GHAPP-ID }}
|
||||
private-key: ${{ steps.get-kv-secrets.outputs.BW-GHAPP-KEY }}
|
||||
- name: Log out from Azure
|
||||
uses: bitwarden/gh-actions/azure-logout@main
|
||||
- name: Validate inputs
|
||||
run: |
|
||||
echo "🔍 Validating required client_payload fields..."
|
||||
|
||||
if [ -z "${_SOURCE_REPO}" ] || [ -z "${_SDK_VERSION}" ] || [ -z "${_ARTIFACTS_RUN_ID}" ] || [ -z "${_ARTIFACT_NAME}" ]; then
|
||||
echo "::error::Missing required client_payload fields"
|
||||
echo "SOURCE_REPO: ${_SOURCE_REPO}"
|
||||
echo "SDK_VERSION: ${_SDK_VERSION}"
|
||||
echo "ARTIFACTS_RUN_ID: ${_ARTIFACTS_RUN_ID}"
|
||||
echo "ARTIFACT_NAME: ${_ARTIFACT_NAME}"
|
||||
echo "CLIENT_LABEL: ${_CLIENT_LABEL}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ All required payload fields are present"
|
||||
- name: Check out clients repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Get Node Version
|
||||
id: retrieve-node-version
|
||||
run: |
|
||||
NODE_NVMRC=$(cat .nvmrc)
|
||||
NODE_VERSION=${NODE_NVMRC/v/''}
|
||||
echo "node_version=$NODE_VERSION" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
node-version: ${{ steps.retrieve-node-version.outputs.node_version }}
|
||||
|
||||
- name: Install Node dependencies
|
||||
run: |
|
||||
echo "📦 Installing Node dependencies with retry logic..."
|
||||
|
||||
RETRY_COUNT=0
|
||||
MAX_RETRIES=3
|
||||
while [ ${RETRY_COUNT} -lt ${MAX_RETRIES} ]; do
|
||||
RETRY_COUNT=$((RETRY_COUNT + 1))
|
||||
echo "🔄 npm ci attempt ${RETRY_COUNT} of ${MAX_RETRIES}..."
|
||||
|
||||
if npm ci; then
|
||||
echo "✅ npm ci successful"
|
||||
break
|
||||
else
|
||||
echo "❌ npm ci attempt ${RETRY_COUNT} failed"
|
||||
[ ${RETRY_COUNT} -lt ${MAX_RETRIES} ] && sleep 5
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${RETRY_COUNT} -eq ${MAX_RETRIES} ]; then
|
||||
echo "::error::npm ci failed after ${MAX_RETRIES} attempts"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Download SDK artifacts
|
||||
uses: bitwarden/gh-actions/download-artifacts@main
|
||||
with:
|
||||
github_token: ${{ steps.app-token.outputs.token }}
|
||||
workflow: build-wasm-internal.yml
|
||||
workflow_conclusion: success
|
||||
run_id: ${{ env._ARTIFACTS_RUN_ID }}
|
||||
artifacts: ${{ env._ARTIFACT_NAME }}
|
||||
repo: ${{ env._SOURCE_REPO }}
|
||||
path: ./sdk-internal
|
||||
if_no_artifact_found: fail
|
||||
|
||||
- name: Override SDK using npm link
|
||||
working-directory: ./
|
||||
run: |
|
||||
echo "🔧 Setting up SDK override using npm link..."
|
||||
echo "📊 SDK Version: ${_SDK_VERSION}"
|
||||
echo "📦 Artifact Source: ${_SOURCE_REPO} run ${_ARTIFACTS_RUN_ID}"
|
||||
|
||||
echo "📋 SDK package contents:"
|
||||
ls -la ./sdk-internal/
|
||||
|
||||
echo "🔗 Creating npm link to SDK package..."
|
||||
if ! npm link ./sdk-internal; then
|
||||
echo "::error::Failed to link SDK package"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Run TypeScript compatibility check
|
||||
run: |
|
||||
|
||||
echo "🔍 Running TypeScript type checking for ${_CLIENT_LABEL} client with SDK version: ${_SDK_VERSION}"
|
||||
echo "🎯 Type checking command: npm run test:types"
|
||||
|
||||
# Add GitHub Step Summary output
|
||||
{
|
||||
echo "## 📊 TypeScript Compatibility Check (${_CLIENT_LABEL})"
|
||||
echo "- **Client**: ${_CLIENT_LABEL}"
|
||||
echo "- **SDK Version**: ${_SDK_VERSION}"
|
||||
echo "- **Source Repository**: ${_SOURCE_REPO}"
|
||||
echo "- **Artifacts Run ID**: ${_ARTIFACTS_RUN_ID}"
|
||||
echo ""
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
|
||||
TYPE_CHECK_START=$(date +%s)
|
||||
|
||||
# Run type check with timeout - exit code determines gh run watch result
|
||||
if timeout 10m npm run test:types; then
|
||||
TYPE_CHECK_END=$(date +%s)
|
||||
TYPE_CHECK_DURATION=$((TYPE_CHECK_END - TYPE_CHECK_START))
|
||||
echo "✅ TypeScript compilation successful for ${_CLIENT_LABEL} client (${TYPE_CHECK_DURATION}s)"
|
||||
echo "✅ **Result**: TypeScript compilation successful" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "No breaking changes detected in ${_CLIENT_LABEL} client for SDK version ${_SDK_VERSION}" >> "$GITHUB_STEP_SUMMARY"
|
||||
else
|
||||
TYPE_CHECK_END=$(date +%s)
|
||||
TYPE_CHECK_DURATION=$((TYPE_CHECK_END - TYPE_CHECK_START))
|
||||
echo "❌ TypeScript compilation failed for ${_CLIENT_LABEL} client after ${TYPE_CHECK_DURATION}s - breaking changes detected"
|
||||
echo "❌ **Result**: TypeScript compilation failed" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "Breaking changes detected in ${_CLIENT_LABEL} client for SDK version ${_SDK_VERSION}" >> "$GITHUB_STEP_SUMMARY"
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user