fix(audio): rebuild timestamps between apad and atrim so FFmpeg 7+ keeps every mixed clip #2631
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: Publish to npm | |
| permissions: {} | |
| on: | |
| push: | |
| tags: | |
| # Stable tags are created only by a merged, reviewed release PR. Direct | |
| # tag pushes are reserved for prerelease channels. | |
| - "v*-*" | |
| pull_request: | |
| types: [closed] | |
| branches: [main] | |
| jobs: | |
| publish: | |
| name: Publish | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| environment: npm-publish | |
| permissions: | |
| contents: write | |
| id-token: write | |
| env: | |
| EXPECTED_RELEASE_SHA: >- | |
| ${{ github.event_name == 'pull_request' | |
| && github.event.pull_request.merge_commit_sha | |
| || github.sha }} | |
| # Stable releases come only from reviewed release PRs. Tag pushes are | |
| # prerelease-only because the trigger pattern requires a hyphenated version. | |
| if: >- | |
| github.event_name == 'push' || | |
| (github.event.pull_request.merged == true && | |
| startsWith(github.event.pull_request.head.ref, 'release/v')) | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| fetch-depth: 0 | |
| # Pin every release to an immutable ref. In particular, a merged | |
| # release PR event exposes main as github.ref, which may advance | |
| # before this job starts; use the event's exact merge commit instead. | |
| ref: ${{ env.EXPECTED_RELEASE_SHA }} | |
| - name: Verify immutable release checkout | |
| run: | | |
| ACTUAL_SHA="$(git rev-parse HEAD)" | |
| EXPECTED_COMMIT_SHA="$(git rev-parse "${EXPECTED_RELEASE_SHA}^{commit}")" | |
| if [ "$ACTUAL_SHA" != "$EXPECTED_COMMIT_SHA" ]; then | |
| echo "::error::Expected release commit $EXPECTED_COMMIT_SHA, checked out $ACTUAL_SHA" | |
| exit 1 | |
| fi | |
| - name: Resolve version | |
| id: version | |
| env: | |
| EVENT_NAME: ${{ github.event_name }} | |
| PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} | |
| run: | | |
| if [ "$EVENT_NAME" = "push" ]; then | |
| VERSION="${GITHUB_REF_NAME#v}" | |
| else | |
| BRANCH="${PR_HEAD_REF}" | |
| VERSION="${BRANCH#release/v}" | |
| fi | |
| echo "version=${VERSION}" >> "$GITHUB_OUTPUT" | |
| # Detect pre-release tag (e.g. 0.1.16-alpha.1 → alpha, 0.1.16-beta.2 → beta) | |
| if [[ "$VERSION" =~ -([a-zA-Z]+) ]]; then | |
| DIST_TAG="${BASH_REMATCH[1]}" | |
| echo "prerelease=true" >> "$GITHUB_OUTPUT" | |
| else | |
| DIST_TAG="latest" | |
| echo "prerelease=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| echo "dist_tag=${DIST_TAG}" >> "$GITHUB_OUTPUT" | |
| echo "Resolved version=${VERSION} dist_tag=${DIST_TAG}" | |
| - name: Validate release channel | |
| env: | |
| VERSION: ${{ steps.version.outputs.version }} | |
| DIST_TAG: ${{ steps.version.outputs.dist_tag }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} | |
| run: node scripts/validate-release-channel.mjs | |
| - name: Create release tag | |
| if: github.event_name == 'pull_request' | |
| env: | |
| VERSION: ${{ steps.version.outputs.version }} | |
| run: | | |
| TAG="v$VERSION" | |
| EXPECTED_TAG_SHA="$(git rev-parse HEAD)" | |
| verify_remote_tag() { | |
| git fetch --force --no-tags origin "+refs/tags/$TAG:refs/tags/$TAG" | |
| ACTUAL_TAG_SHA="$(git rev-parse "refs/tags/$TAG^{commit}")" | |
| if [ "$ACTUAL_TAG_SHA" != "$EXPECTED_TAG_SHA" ]; then | |
| echo "::error::Release tag $TAG points to $ACTUAL_TAG_SHA, expected $EXPECTED_TAG_SHA" | |
| exit 1 | |
| fi | |
| echo "Release tag $TAG already exists at the expected commit — skipping" | |
| } | |
| if [ -n "$(git ls-remote --refs origin "refs/tags/$TAG")" ]; then | |
| verify_remote_tag | |
| else | |
| git tag --no-sign "$TAG" "$EXPECTED_TAG_SHA" | |
| if ! git push origin "refs/tags/$TAG"; then | |
| # A concurrent retry may have created the tag after ls-remote. | |
| git tag -d "$TAG" | |
| verify_remote_tag | |
| fi | |
| fi | |
| - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: 24 | |
| registry-url: "https://registry.npmjs.org" | |
| - run: corepack enable | |
| - run: corepack prepare pnpm@10.17.1 --activate | |
| - run: bun install --frozen-lockfile | |
| - run: bun run build | |
| - run: bun run verify:packed-manifests | |
| - name: Publish packages | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| VERSION: ${{ steps.version.outputs.version }} | |
| DIST_TAG: ${{ steps.version.outputs.dist_tag }} | |
| run: | | |
| FAILED=0 | |
| publish_pkg() { | |
| local filter="$1" | |
| local name="$2" | |
| # Check if this version is already published | |
| if npm view "${name}@${VERSION}" version >/dev/null 2>&1; then | |
| echo "⏭️ ${name}@${VERSION} already published — skipping" | |
| return 0 | |
| fi | |
| echo "📦 Publishing ${name}@${VERSION}..." | |
| if pnpm --filter "$filter" publish --access public --no-git-checks --tag "$DIST_TAG"; then | |
| echo "✅ ${name}@${VERSION} published" | |
| else | |
| echo "❌ ${name}@${VERSION} failed to publish" | |
| FAILED=1 | |
| fi | |
| } | |
| publish_pkg "@hyperframes/parsers" "@hyperframes/parsers" | |
| publish_pkg "@hyperframes/lint" "@hyperframes/lint" | |
| publish_pkg "@hyperframes/studio-server" "@hyperframes/studio-server" | |
| publish_pkg "@hyperframes/core" "@hyperframes/core" | |
| publish_pkg "@hyperframes/sdk" "@hyperframes/sdk" | |
| publish_pkg "@hyperframes/engine" "@hyperframes/engine" | |
| publish_pkg "@hyperframes/player" "@hyperframes/player" | |
| publish_pkg "@hyperframes/producer" "@hyperframes/producer" | |
| publish_pkg "@hyperframes/shader-transitions" "@hyperframes/shader-transitions" | |
| publish_pkg "@hyperframes/studio" "@hyperframes/studio" | |
| publish_pkg "@hyperframes/aws-lambda" "@hyperframes/aws-lambda" | |
| publish_pkg "@hyperframes/gcp-cloud-run" "@hyperframes/gcp-cloud-run" | |
| # CLI is @hyperframes/cli in the monorepo but published as unscoped "hyperframes" on npm. | |
| # Rewrite the name in package.json before publishing, then use npm publish directly | |
| # since pnpm --filter won't match the rewritten name. | |
| if npm view "hyperframes@${VERSION}" version >/dev/null 2>&1; then | |
| echo "⏭️ hyperframes@${VERSION} already published — skipping" | |
| else | |
| node -e " | |
| const fs = require('fs'); | |
| const p = 'packages/cli/package.json'; | |
| const pkg = JSON.parse(fs.readFileSync(p, 'utf8')); | |
| pkg.name = 'hyperframes'; | |
| fs.writeFileSync(p, JSON.stringify(pkg, null, 2) + '\n'); | |
| " | |
| echo "📦 Publishing hyperframes@${VERSION}..." | |
| if (cd packages/cli && npm publish --access public --tag "$DIST_TAG"); then | |
| echo "✅ hyperframes@${VERSION} published" | |
| else | |
| echo "❌ hyperframes@${VERSION} failed to publish" | |
| FAILED=1 | |
| fi | |
| fi | |
| if [ "$FAILED" -ne 0 ]; then | |
| echo "::error::One or more packages failed to publish" | |
| exit 1 | |
| fi | |
| - name: Create GitHub Release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| VERSION: ${{ steps.version.outputs.version }} | |
| PRERELEASE: ${{ steps.version.outputs.prerelease }} | |
| REPO: ${{ github.repository }} | |
| run: | | |
| NOTES_FILE="releases/v${VERSION}.md" | |
| # Skip if release already exists (idempotent re-runs) | |
| if gh release view "v${VERSION}" --repo "$REPO" >/dev/null 2>&1; then | |
| echo "Release v${VERSION} already exists — skipping" | |
| else | |
| FLAGS=(--repo "$REPO" --title "v${VERSION}") | |
| if [ -f "$NOTES_FILE" ]; then | |
| FLAGS+=(--notes-file "$NOTES_FILE") | |
| else | |
| echo "No reviewed release notes found at $NOTES_FILE — using GitHub generated notes" | |
| FLAGS+=(--generate-notes) | |
| fi | |
| if [ "$PRERELEASE" = "true" ]; then | |
| FLAGS+=(--prerelease) | |
| fi | |
| gh release create "v${VERSION}" "${FLAGS[@]}" | |
| fi |