Conversation
* bump react and react-dom package versions * update unsafe ref access when merging internal and customer refs * upgrade storybook (storybook@latest upgrade) * upgrade react eslint plugin and disable its new rules for now * migrate CSF2 stories to CSF3 format (https://storybook.js.org/blog/storybook-csf3-is-here/) * upgrade react testing library and replace outdated imports * upgrade react-native & other Expo-managed dependencies * introduce new test-expo app for mobile testing * remove react-native accessibility engine and replace with our own fork compatible with our react native version * remove deprecated @testing-library/jest-native and migrate tests away from react-test-renderer * migrate toHaveAccessibilityState to granular matchers (toBeChecked, toBeSelected, toBeDisabled) * update formatting of yarn constraint for matching dependency versions * create new yarn constraint for enforcing matching peer and dev dependencies * remove odd react-dom peer dep on common package * remove unused peer desps of cds-mobile * remove cds-mobile useStatusBarHeight and swtich to using safe area context insets (#376) * setup manual mocks for react-native-worklets * update versions referenced in mobile docs component metadata * fix layout issues in tooltip and tour for android edge to edge display * rewrite mobile stepper animation using reanimated (#387)
* chore: fix react version resolution issue
* Add isolated prop to web ThemeProvider and update managed Portal component * Add documentation for PortalProvider setup * Improve documentation around ThemeProvider --------- Co-authored-by: Cody Nova <cody.nova@coinbase.com>
* feat: consolidate border props in Cell component * fix: lint issues * chore: address code review feedback * feat: refactored useResolveResponsiveProp
chore: merge master into cdsv9
…or mobile title Text (#401) * feat: deprecated individual Text components * feat: updated internal usage of individual text components * fix: lint issue * feat: updated deprecation comment for title componnents in mobile to prevent a11y regression * feat: added default accessibilityRole for header in mobile * feat: updated web doc for Text on a11y
* feat: added inverse variant and modified tertiary variant for Button * feat: address code reivew by adjusting doc site wording and remvoe uncessary unit tests * feat: removed foregroundMuted variant from Button * feat: removed foregroundMuted variant in Button and IconButton * feat: added runtime fallback to prevent crashing by the old variant * feat: clean up examples and revised safety net * feat: clean up remaining foregroundMuted * feat: remove safety fallback for Button variants
* feat: shortened Pressable CSS variables * chore: trigger CI rerun Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
* chore: remove interactable height constant and refactor several components to use content-based sizing instead of predetermined height * chore: remove more fixed dimensions from components * refactor InputStack to enable simpler spacing/layout in select/combobox components
…to internal padding properties
…avigation ui in edge to edge android
…bile-visualization package
* feat: simplify carousel pagination in v9 * feat: limit title line count * Fix title on mobile
🟡 Heimdall Review Status
🟡
|
| Code Owner | Status | Calculation | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| ui-systems-eng-team |
🟡
0/1
|
Denominator calculation
|
* feat (CDS-1613): button variant migrator * chore: added jsdoc for button variant transform
…v9 (#553) Made-with: Cursor
|
|
||
| // Replace assets/index.android.bundle in the APK (cd into patchDir so zip path is correct) | ||
| console.log(`\nPatching bundle into APK: ${apk}...`); | ||
| execSync(`zip -u ${apk} assets/index.android.bundle`, { cwd: patchDir, stdio: 'inherit' }); |
Check warning
Code scanning / CodeQL
Shell command built from environment values Medium test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 15 days ago
In general, to fix this type of problem you should stop constructing a single shell command string with interpolated environment or path values and instead pass the command and its arguments separately (for example, using execFileSync or spawn with an argument array). This prevents the shell from re‑parsing the path value and interpreting special characters.
For this specific code, the best fix with minimal behavioral changes is:
- Replace the
execSynccall on line 138 that uses a backticked string with a call tospawn(already imported) orexecFileSync-style usage where:- The command is
"zip". - The arguments are
['-u', apk, 'assets/index.android.bundle']. cwdremainspatchDir, andstdio: 'inherit'is preserved.- We ensure the process exits successfully, otherwise we throw an error to mimic
execSync’s behavior.
- The command is
Because spawn is already imported at the top, we can create a small helper in this file (or inline logic) to run zip synchronously and check its exit code. Since we must not assume other project utilities beyond what we see, we’ll add a small runZipUpdate helper function within this file, just above applyBundle, which uses spawn to execute zip with an argument array and returns a promise that rejects on non‑zero exit. We then await it from applyBundle. This preserves functionality while removing the shell command construction.
No other lines need to change, and no new imports are required.
| @@ -135,8 +135,25 @@ | ||
|
|
||
| // Replace assets/index.android.bundle in the APK (cd into patchDir so zip path is correct) | ||
| console.log(`\nPatching bundle into APK: ${apk}...`); | ||
| execSync(`zip -u ${apk} assets/index.android.bundle`, { cwd: patchDir, stdio: 'inherit' }); | ||
| await new Promise((resolve, reject) => { | ||
| const child = spawn('zip', ['-u', apk, 'assets/index.android.bundle'], { | ||
| cwd: patchDir, | ||
| stdio: 'inherit', | ||
| }); | ||
|
|
||
| child.on('error', (err) => { | ||
| reject(err); | ||
| }); | ||
|
|
||
| child.on('exit', (code) => { | ||
| if (code === 0) { | ||
| resolve(); | ||
| } else { | ||
| reject(new Error(`zip exited with code ${code}`)); | ||
| } | ||
| }); | ||
| }); | ||
|
|
||
| // Re-align (zip modification breaks alignment) then re-sign with debug keystore | ||
| execSync(`zipalign -f 4 ${apk} ${alignedApk}`, { stdio: 'inherit' }); | ||
| await fs.rename(alignedApk, apk); |
| execSync(`zip -u ${apk} assets/index.android.bundle`, { cwd: patchDir, stdio: 'inherit' }); | ||
|
|
||
| // Re-align (zip modification breaks alignment) then re-sign with debug keystore | ||
| execSync(`zipalign -f 4 ${apk} ${alignedApk}`, { stdio: 'inherit' }); |
Check warning
Code scanning / CodeQL
Shell command built from environment values Medium test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 15 days ago
In general, the fix is to avoid building a single shell command string that includes environment- or configuration-derived paths, and instead execute the program directly with an argument array so that the shell is not invoked and the arguments are not reinterpreted. For Node.js, this means using execFileSync (or spawn/spawnSync) with a command name and an array of arguments, rather than execSync with a combined string.
Concretely in AndroidBuilder.mjs, we should:
- Import
execFileSyncfromnode:child_process. - Replace the three
execSynccalls inapplyBundlewithexecFileSync(orspawnSync) using argument arrays:zip -u ${apk} assets/index.android.bundle→execFileSync('zip', ['-u', apk, 'assets/index.android.bundle'], { cwd: patchDir, stdio: 'inherit' }).zipalign -f 4 ${apk} ${alignedApk}→execFileSync('zipalign', ['-f', '4', apk, alignedApk], { stdio: 'inherit' }).apksigner sign --ks ${debugKeystore} --ks-pass pass:android --key-pass pass:android ${apk}→execFileSync('apksigner', ['sign', '--ks', debugKeystore, '--ks-pass', 'pass:android', '--key-pass', 'pass:android', apk], { stdio: 'inherit' }).
These changes keep the behavior identical (same commands, same working directory, same stdio handling) while ensuring environment-derived paths are passed as raw arguments rather than interpolated into a shell command string.
| @@ -1,4 +1,4 @@ | ||
| import { execSync, spawn } from 'node:child_process'; | ||
| import { execFileSync, execSync, spawn } from 'node:child_process'; | ||
| import fs from 'node:fs/promises'; | ||
| import path from 'node:path'; | ||
|
|
||
| @@ -135,15 +135,19 @@ | ||
|
|
||
| // Replace assets/index.android.bundle in the APK (cd into patchDir so zip path is correct) | ||
| console.log(`\nPatching bundle into APK: ${apk}...`); | ||
| execSync(`zip -u ${apk} assets/index.android.bundle`, { cwd: patchDir, stdio: 'inherit' }); | ||
| execFileSync('zip', ['-u', apk, 'assets/index.android.bundle'], { | ||
| cwd: patchDir, | ||
| stdio: 'inherit', | ||
| }); | ||
|
|
||
| // Re-align (zip modification breaks alignment) then re-sign with debug keystore | ||
| execSync(`zipalign -f 4 ${apk} ${alignedApk}`, { stdio: 'inherit' }); | ||
| execFileSync('zipalign', ['-f', '4', apk, alignedApk], { stdio: 'inherit' }); | ||
| await fs.rename(alignedApk, apk); | ||
|
|
||
| const debugKeystore = path.resolve(process.env.HOME, '.android/debug.keystore'); | ||
| execSync( | ||
| `apksigner sign --ks ${debugKeystore} --ks-pass pass:android --key-pass pass:android ${apk}`, | ||
| execFileSync( | ||
| 'apksigner', | ||
| ['sign', '--ks', debugKeystore, '--ks-pass', 'pass:android', '--key-pass', 'pass:android', apk], | ||
| { stdio: 'inherit' }, | ||
| ); | ||
|
|
|
|
||
| const debugKeystore = path.resolve(process.env.HOME, '.android/debug.keystore'); | ||
| execSync( | ||
| `apksigner sign --ks ${debugKeystore} --ks-pass pass:android --key-pass pass:android ${apk}`, |
Check warning
Code scanning / CodeQL
Shell command built from environment values Medium test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 15 days ago
In general, to fix this class of problem you should avoid constructing a single shell command string with interpolated environment-derived values. Instead, call the command with its arguments specified separately so that Node bypasses the shell and passes arguments directly to the executable. For child_process.execSync, that means switching to execFileSync (or using spawn/spawnSync) with an argument array; each path (like apk and debugKeystore) then becomes a separate element in that array and is not subject to shell parsing.
For this specific code, the safest change that preserves behavior is:
- Replace the
execSyncinvocation at lines 145–148 with a call toexecFileSync('apksigner', [...args...], { stdio: 'inherit' }). - Build the argument list as an array:
['sign', '--ks', debugKeystore, '--ks-pass', 'pass:android', '--key-pass', 'pass:android', apk]. - Import
execFileSyncfromnode:child_processalongside the existing imports so it is available. - Leave the rest of the method unchanged; we are not altering options, flags, or logging, just how the command is invoked.
Concretely:
- In
apps/test-expo/scripts/utils/AndroidBuilder.mjs, update the import on line 1 fromimport { execSync, spawn } from 'node:child_process';to also importexecFileSync. - Replace the
execSynccall forapksigner(lines 145–148) with a correspondingexecFileSynccall using an argument array, keepingstdio: 'inherit'in the options.
No other regions or files need changes to fix this particular alert.
| @@ -1,4 +1,4 @@ | ||
| import { execSync, spawn } from 'node:child_process'; | ||
| import { execFileSync, execSync, spawn } from 'node:child_process'; | ||
| import fs from 'node:fs/promises'; | ||
| import path from 'node:path'; | ||
|
|
||
| @@ -142,8 +142,9 @@ | ||
| await fs.rename(alignedApk, apk); | ||
|
|
||
| const debugKeystore = path.resolve(process.env.HOME, '.android/debug.keystore'); | ||
| execSync( | ||
| `apksigner sign --ks ${debugKeystore} --ks-pass pass:android --key-pass pass:android ${apk}`, | ||
| execFileSync( | ||
| 'apksigner', | ||
| ['sign', '--ks', debugKeystore, '--ks-pass', 'pass:android', '--key-pass', 'pass:android', apk], | ||
| { stdio: 'inherit' }, | ||
| ); | ||
|
|
1. restored and deprecated progressSpringConfig prop and defaultProgressSpringConfig; 2. restored and deprecated animationConfig.
* feat: add indeterminate ProgressCircle (#501) * feat: add indeterminate ProgressCircle, unify progress size and float-label math - Add indeterminate prop to ProgressCircle (web & mobile): spinning state with configurable weight, default stroke ratio 0.11; animate full SVG on mobile, CSS keyframes on web; hide default content when indeterminate. - Add getProgressSize(weight) in common and deprecate useProgressSize; use getProgressSize in ProgressBar and ProgressCircle on both platforms. - Simplify ProgressBarWithFloatLabel (web & mobile): remove usePreviousValues, useIsoEffect, and imperative animation; use shared getEndTranslateX so float label trailing edge follows fill end (containerWidth * progress - textWidth); web uses useMotionProps + MotionBox, mobile animates translateX to target. - ProgressBar/ProgressCircle: progress optional with default 0; add originX/ originY in getProgressCircleParams; web ProgressCircle uses pathLength=1. - Deprecate Spinner (web & mobile) in favor of indeterminate ProgressCircle. - ProgressBar tests: update float-label position expectation (80) and accept transform none/translateX(0) for zero progress; iconSvgMap regenerated. * update test and deprecation message * add more button stories * a11y fix * remove 0.11 * add progressCircleSize prop * update changelogs and package versions * add progressCircleSize prop to IconButton * fix removal version * chore: deprecate CardGroup (#560) * chore: deprecate CardGroup * Update changelog * feat: added cds skills for distribution (#561) * chore: deprecate old card (#562) * chore: deprecate old card 1. derpecated Card and related components and types 2. added derepcate-cds-api-skill * update changelogs * tweaks --------- Co-authored-by: Hunter Copp <huntercolecopp@gmail.com> Co-authored-by: Harry <ruikun.hao@coinbase.com>
* chore: deprecate visualization packages --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add transform for useMergerefs * organize * cleanup * include both internal and open source name space * add package scope
* fix: scrubber beacon label immediate updates * Bump version
* fix: mobile scrubber initial load glitch * Bump version
* chore: bump version to 1.0.1 and update visual verification instructions * Update version in cds-code and design-to-code skills to 1.0.1 * Revise visual verification instructions to include asking users for screenshots when inspection tooling is unavailable * feat: added readme for human readers * chore: format * feat: dynamically determine cds import scope for skill * fix: exclude v7 packages from CDS import scope determination * feat: enhance CDS package discovery to include runtime detection - Updated the discovery script to identify the CDS runtime (web or mobile) based on installed packages. - Revised documentation to reflect changes in the discovery process, consolidating steps for clarity.
* [StepSecurity] Apply security best practices Signed-off-by: StepSecurity Bot <bot@stepsecurity.io> * Fix lint --------- Signed-off-by: StepSecurity Bot <bot@stepsecurity.io> Co-authored-by: stepsecurity-app[bot] <188008098+stepsecurity-app[bot]@users.noreply.github.com> Co-authored-by: Hunter Copp <huntercolecopp@gmail.com>
What changed? Why?
Root cause (required for bugfixes)
UI changes
Testing
How has it been tested?
Testing instructions
Illustrations/Icons Checklist
Required if this PR changes files under
packages/illustrations/**orpackages/icons/**Change management
type=routine
risk=low
impact=sev5
automerge=false