utils: Smart CDN URL grammar — parse, unsigned build, strip auth, trusted baseUrl #1389
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| workflow_dispatch: | |
| pull_request: | |
| push: | |
| branches: | |
| - main | |
| tags: | |
| - '*' | |
| schedule: | |
| - cron: '0 8 * * *' | |
| jobs: | |
| lockfile: | |
| name: Lockfile guard | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' || github.event_name == 'push' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Ensure yarn.lock matches dependency changes | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }} | |
| HEAD_SHA: ${{ github.sha }} | |
| run: | | |
| set -euo pipefail | |
| base="${BASE_SHA:-}" | |
| head="${HEAD_SHA:-}" | |
| if [ -z "$base" ] || [ "$base" = "0000000000000000000000000000000000000000" ]; then | |
| echo "No base sha available; skipping lockfile guard." | |
| exit 0 | |
| fi | |
| node <<'NODE' | |
| const { execSync } = require('node:child_process') | |
| const base = process.env.BASE_SHA | |
| const head = process.env.HEAD_SHA | |
| const depKeys = [ | |
| 'dependencies', | |
| 'devDependencies', | |
| 'peerDependencies', | |
| 'optionalDependencies', | |
| ] | |
| const diffNames = execSync(`git diff --name-only ${base} ${head}`, { | |
| encoding: 'utf8', | |
| }) | |
| .trim() | |
| .split('\n') | |
| .filter(Boolean) | |
| const packageFiles = diffNames.filter((file) => { | |
| if (!file.endsWith('package.json')) { | |
| return false | |
| } | |
| return !file.startsWith('docs/fingerprint/') | |
| }) | |
| const lockfileChanged = diffNames.includes('yarn.lock') | |
| if (packageFiles.length === 0) { | |
| process.exit(0) | |
| } | |
| const hasDependencyChanges = packageFiles.some((file) => { | |
| let before = {} | |
| let after = {} | |
| try { | |
| before = JSON.parse(execSync(`git show ${base}:${file}`, { encoding: 'utf8' })) | |
| } catch { | |
| return true | |
| } | |
| try { | |
| after = JSON.parse(execSync(`git show ${head}:${file}`, { encoding: 'utf8' })) | |
| } catch { | |
| return true | |
| } | |
| return depKeys.some((key) => { | |
| const lhs = before[key] ?? {} | |
| const rhs = after[key] ?? {} | |
| return JSON.stringify(lhs) !== JSON.stringify(rhs) | |
| }) | |
| }) | |
| if (hasDependencyChanges && !lockfileChanged) { | |
| console.error('yarn.lock must be updated when dependency ranges change in package.json.') | |
| process.exit(1) | |
| } | |
| NODE | |
| pack: | |
| name: Build package | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 22 | |
| - run: corepack yarn install --immutable | |
| - run: corepack yarn run pack | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: package | |
| path: '*.tgz' | |
| verify: | |
| name: Verify (fast) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - run: corepack yarn install --immutable | |
| - run: corepack yarn verify | |
| verify-full: | |
| name: Verify (full) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - run: corepack yarn install --immutable | |
| - run: corepack yarn verify:full | |
| release-dry-run: | |
| name: Release dry run | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 22 | |
| registry-url: https://registry.npmjs.org | |
| - run: npm install -g npm@11.5.1 | |
| - run: corepack yarn install --immutable | |
| - run: corepack yarn tsc:utils | |
| - run: corepack yarn tsc:zod | |
| - run: corepack yarn tsc:node | |
| - run: corepack yarn changeset:version:release | |
| - run: corepack yarn release:pack:dry-run | |
| unit: | |
| name: Unit tests (Node ${{ matrix.node }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| node: | |
| - 20 | |
| - 22 | |
| - 24 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ matrix.node }} | |
| - run: corepack yarn install --immutable | |
| # Root unit tests execute TypeScript scripts via Node's strip-types support. | |
| # Keep those on Node 24+; Node 20/22 only run @transloadit/node unit tests. | |
| - run: corepack yarn test:unit | |
| if: matrix.node == 24 | |
| - run: corepack yarn workspace @transloadit/node test:unit | |
| if: matrix.node != 24 | |
| - name: Upload coverage reports artifact | |
| if: matrix.node == 24 | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: coverage-reports | |
| path: packages/node/coverage/ | |
| e2e: | |
| name: E2E tests | |
| # Run on push/schedule/dispatch, or on PRs only if from same repo (not forks) | |
| # This protects secrets from being exposed to fork PRs | |
| if: > | |
| github.event_name != 'pull_request' || | |
| github.event.pull_request.head.repo.full_name == github.repository | |
| runs-on: ubuntu-latest | |
| env: | |
| NODE_OPTIONS: --trace-deprecation --trace-warnings | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - run: corepack yarn install --immutable | |
| - name: Download cloudflared | |
| run: | | |
| curl -fsSL --retry 5 --retry-all-errors --retry-delay 2 -o cloudflared-linux-amd64 https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 | |
| chmod +x cloudflared-linux-amd64 | |
| # can be used for debugging: | |
| # - name: Setup tmate session | |
| # uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 | |
| - run: corepack yarn test | |
| env: | |
| CLOUDFLARED_PATH: ${{ github.workspace }}/cloudflared-linux-amd64 | |
| DEBUG: 'transloadit:*' | |
| TRANSLOADIT_KEY: ${{ secrets.TRANSLOADIT_KEY }} | |
| TRANSLOADIT_SECRET: ${{ secrets.TRANSLOADIT_SECRET }} | |
| - name: Run MCP server e2e tests | |
| run: corepack yarn workspace @transloadit/mcp-server test:e2e | |
| - name: Run notify-url-relay real e2e test | |
| run: corepack yarn workspace @transloadit/notify-url-relay test:real | |
| env: | |
| TRANSLOADIT_KEY: ${{ secrets.TRANSLOADIT_KEY }} | |
| TRANSLOADIT_SECRET: ${{ secrets.TRANSLOADIT_SECRET }} | |
| TRANSLOADIT_ENDPOINT: ${{ secrets.TRANSLOADIT_ENDPOINT }} | |
| - name: Generate the badge from the json-summary | |
| run: node --experimental-strip-types packages/node/test/generate-coverage-badge.ts packages/node/coverage/coverage-summary.json | |
| - name: Move HTML report and badge to the correct location | |
| run: | | |
| mv packages/node/coverage/lcov-report static-build | |
| mv coverage-badge.svg static-build/ | |
| - name: Upload coverage site artifact | |
| if: github.event_name != 'pull_request' | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: coverage-site | |
| path: static-build | |
| pages: | |
| name: Publish coverage Pages | |
| needs: e2e | |
| runs-on: ubuntu-latest | |
| if: github.event_name != 'pull_request' | |
| permissions: | |
| contents: read | |
| pages: write | |
| id-token: write | |
| environment: | |
| name: github-pages | |
| url: ${{ steps.deployment.outputs.page_url }} | |
| steps: | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: coverage-site | |
| path: static-build | |
| - uses: actions/upload-pages-artifact@v5 | |
| with: | |
| path: static-build | |
| - name: Deploy coverage to GitHub Pages | |
| id: deployment | |
| uses: actions/deploy-pages@v5 | |
| coverage: | |
| name: Upload coverage | |
| needs: unit | |
| runs-on: ubuntu-latest | |
| if: github.ref == 'refs/heads/main' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: coverage-reports | |
| path: coverage | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v6.0.2 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: ./coverage/lcov.info | |
| flags: unittests | |
| name: node-sdk | |
| fail_ci_if_error: true | |
| slack-on-failure: | |
| name: Slack notification | |
| needs: [e2e] | |
| if: ${{ failure() && github.ref == 'refs/heads/main' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Send Slack notification | |
| env: | |
| SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} | |
| SLACK_TEXT: >- | |
| ${{ github.workflow }} failed for ${{ github.repository }} on ${{ github.ref_name }}: | |
| ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| run: | | |
| node -e "process.stdout.write(JSON.stringify({ text: process.env.SLACK_TEXT }))" | | |
| curl --fail-with-body -X POST -H 'Content-type: application/json' --data-binary @- "$SLACK_WEBHOOK_URL" |