Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# CI for the action itself: unit tests for the components, and a check that the
# committed bundle (dist/index.js, which action.yml runs verbatim) is fresh and
# loads under Node.
name: ci
on:
pull_request:
push:
branches: [main]

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 24
- name: Install bit
run: |
npx --yes @teambit/bvm install 2.2.115
echo "$HOME/bin" >> "$GITHUB_PATH"
- name: Install dependencies
run: bit install
- name: Test
run: bit test
- name: Verify the committed bundle
run: node scripts/verify-bundle.mjs
2 changes: 1 addition & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ inputs:
required: false
default: bit-sync/main
runs:
using: node20
using: node24
# Committed esbuild bundle -- see scripts/bundle-action.mjs. Must be ESM
# (the root package.json is `"type": "module"`); `npm run verify-bundle`
# asserts it is both fresh and loadable.
Expand Down
2 changes: 1 addition & 1 deletion dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ function scopesInComponentIds(componentIds) {
function isLaneRelevantToScope(componentIds, repoScope) {
if (!componentIds || !repoScope)
return true;
const scopes = scopesInComponentIds(componentIds);
const scopes = scopesInComponentIds(Array.isArray(componentIds) ? componentIds.join(",") : String(componentIds));
if (scopes.length === 0)
return true;
return scopes.includes(repoScope);
Expand Down
27 changes: 27 additions & 0 deletions git-sync/git-sync/event-router/event-router.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,33 @@ describe('routeEvent', () => {
});
});

it('accepts componentIds as an array (API-created webhooks, hand-rolled dispatches)', () => {
expect(
routeEvent({
...base,
eventName: 'repository_dispatch',
dispatchType: 'bit-export',
repoScope: 'acme.cards',
clientPayload: {
laneId: 'acme.cards/cross-scope',
componentIds: ['acme.shop/bar@2.0.0', 'acme.cards/foo@1.0.0'],
},
})
).toEqual({ kind: 'run', args: ['sync', 'acme.cards/cross-scope'] });
});

it('treats an empty componentIds array as absent (fails open)', () => {
expect(
routeEvent({
...base,
eventName: 'repository_dispatch',
dispatchType: 'bit-export',
repoScope: 'acme.cards',
clientPayload: { laneId: '', componentIds: [] },
})
).toEqual({ kind: 'run', args: ['sync', '--main'] });
});

it('fails open (routes) when componentIds is absent, even with repoScope set', () => {
expect(
routeEvent({
Expand Down
9 changes: 5 additions & 4 deletions git-sync/git-sync/event-router/event-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ export type RouterInput = {
* cross-scope-lane relevance filter (see `repoScope` below) to decide
* whether this repo has any stake in a lane export before routing it.
* Absent/empty is NOT a signal of anything — it just means the filter
* can't run, so it fails open (see `isLaneRelevantToScope`).
* can't run, so it fails open (see `isLaneRelevantToScope`). A webhook
* created through the API, or a hand-rolled dispatch, may send an array.
*/
componentIds?: string;
componentIds?: string | string[];
};
/** push: refs/heads/<branch>. */
ref?: string;
Expand Down Expand Up @@ -179,9 +180,9 @@ function scopesInComponentIds(componentIds: string): string[] {
* whose content isn't entirely inside `defaultScope`, so failing open here
* only means the halt happens in `bit ci` instead of being pre-empted here.
*/
function isLaneRelevantToScope(componentIds: string | undefined, repoScope: string | undefined): boolean {
function isLaneRelevantToScope(componentIds: string | string[] | undefined, repoScope: string | undefined): boolean {
if (!componentIds || !repoScope) return true;
const scopes = scopesInComponentIds(componentIds);
const scopes = scopesInComponentIds(Array.isArray(componentIds) ? componentIds.join(',') : String(componentIds));
if (scopes.length === 0) return true;
return scopes.includes(repoScope);
}
Expand Down
2 changes: 1 addition & 1 deletion scripts/bundle-action.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const bundleOptions = {
entryPoints: [join(repoRoot, 'git-sync/git-sync/action/run.ts')],
bundle: true,
platform: 'node',
target: 'node20',
target: 'node24',
format: 'esm',
absWorkingDir: repoRoot,
};
Expand Down
Loading