diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index c11eaa5f..683888ff 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -86,8 +86,7 @@ jobs: containerfiles: | ./packages/web/infra/Containerfile image: ${{ env.REGISTRY_IMAGE }} - tags: ${{ steps.meta.outputs.tags }} - working-directory: packages/web + tags: ${{ steps.meta.outputs.tag }} oci: true platforms: linux/amd64,linux/arm64 labels: | @@ -95,16 +94,16 @@ jobs: org.opencontainers.image.revision=${{ github.sha }} org.opencontainers.image.created=${{ github.event.head_commit.timestamp }} - - name: Push To GHCR id: push-to-registry uses: redhat-actions/push-to-registry@v2 with: image: ${{ steps.build-container.outputs.image }} - tags: ${{ steps.build-container.outputs.tags }} + tags: ${{ steps.build-container.outputs.tags || steps.meta.outputs.tag }} registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Print image URL run: echo "Image pushed to ${{ steps.push-to-registry.outputs.registry-paths }}" diff --git a/.github/workflows/release-packages.yml b/.github/workflows/release-packages.yml index 2719d397..e70b9f0c 100644 --- a/.github/workflows/release-packages.yml +++ b/.github/workflows/release-packages.yml @@ -4,16 +4,22 @@ on: workflow_dispatch: inputs: packages: - description: 'Packages to release (comma-separated, or "all" for all packages)' + description: 'Packages to release (comma-separated, or "all")' required: false default: 'all' + bump: + description: 'Semver bump (patch | minor | major)' + required: false + default: 'patch' jobs: release: runs-on: ubuntu-latest permissions: - contents: read - id-token: write # <-- required for JSR OIDC + contents: write # we commit the bumped versions back + id-token: write # required for JSR OIDC + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} steps: - name: Checkout code uses: actions/checkout@v4 @@ -29,21 +35,16 @@ jobs: node-version: 22 cache: pnpm cache-dependency-path: '**/pnpm-lock.yaml' + registry-url: 'https://registry.npmjs.org' - name: Install dependencies run: pnpm install --frozen-lockfile - - name: Configure npm auth - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - run: | - pnpm config set //registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN} - pnpm config set registry https://registry.npmjs.org/ - - name: Resolve package list id: pkgs shell: bash run: | + set -euo pipefail if [ "${{ github.event.inputs.packages }}" = "all" ] || [ -z "${{ github.event.inputs.packages }}" ]; then mapfile -t TARGETS < <(ls -d packages/* | grep -v 'packages/web') else @@ -52,61 +53,91 @@ jobs: fi printf '%s\n' "${TARGETS[@]}" | paste -sd, - > targets.txt echo "list=$(cat targets.txt)" >> "$GITHUB_OUTPUT" + echo "Targets: $(cat targets.txt)" - - name: Build selected packages (tsdown) + - name: Bump package.json versions (no git tag) + shell: bash run: | + set -euo pipefail + BUMP="${{ github.event.inputs.bump }}" IFS=',' read -ra TARGETS <<< "${{ steps.pkgs.outputs.list }}" for dir in "${TARGETS[@]}"; do - echo "Building $dir" - pnpm --filter "./$dir" run build + if [ -f "$dir/package.json" ]; then + echo "Bumping $dir -> $BUMP" + (cd "$dir" && npm version "$BUMP" --no-git-tag-version --allow-same-version) + fi done - - name: Sync jsr.json version from package.json + - name: Generate jsr.json from package.json (pkg-to-jsr) + shell: bash run: | + set -euo pipefail IFS=',' read -ra TARGETS <<< "${{ steps.pkgs.outputs.list }}" for dir in "${TARGETS[@]}"; do - if [ -f "$dir/jsr.json" ] && [ -f "$dir/package.json" ]; then - PKG_VER=$(jq -r .version "$dir/package.json") - jq --arg v "$PKG_VER" '.version = $v' "$dir/jsr.json" > "$dir/jsr.json.tmp" && mv "$dir/jsr.json.tmp" "$dir/jsr.json" - echo "Updated $dir/jsr.json to version $PKG_VER" + if [ -f "$dir/package.json" ]; then + echo "Generating jsr.json for $dir" + pnpm dlx pkg-to-jsr --root "$dir" + # # Optional: show result + # jq -C . "$dir/jsr.json" || cat "$dir/jsr.json" fi done + + - name: Commit version bumps + shell: bash + run: | + set -euo pipefail + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add packages/*/package.json packages/*/jsr.json 2>/dev/null || true + if ! git diff --cached --quiet; then + git commit -m "chore(release): bump package versions (${{ github.event.inputs.bump }})" + git push + else + echo "No changes to commit." + fi + + - name: Build selected packages + shell: bash + run: | + set -euo pipefail + IFS=',' read -ra TARGETS <<< "${{ steps.pkgs.outputs.list }}" + for dir in "${TARGETS[@]}"; do + echo "Building $dir" + pnpm --filter "./$dir" run build + done + - name: Publish to JSR (OIDC) + shell: bash run: | set -euo pipefail IFS=',' read -ra TARGETS <<< "${{ steps.pkgs.outputs.list }}" for dir in "${TARGETS[@]}"; do if [ -f "$dir/jsr.json" ]; then echo "Publishing $dir to JSR via OIDC…" - cd "$dir" - [ -d dist ] || pnpm run build - if ! npx --yes jsr publish 2>&1 | tee jsr_publish.log; then - echo "JSR publish failed for $dir. Error output:" - cat jsr_publish.log - fi - cd - >/dev/null + ( cd "$dir" + [ -d dist ] || pnpm run build + npx --yes jsr publish + ) fi done - - name: Replace exports entry in package.json + - name: Configure npm auth run: | - tmp=$(mktemp) - jq '.exports["."] = "./dist/mod.mjs"' package.json > "$tmp" \ - && mv "$tmp" package.json + pnpm config set //registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN} + pnpm config set registry https://registry.npmjs.org/ - name: Publish to npm + shell: bash run: | set -euo pipefail IFS=',' read -ra TARGETS <<< "${{ steps.pkgs.outputs.list }}" for dir in "${TARGETS[@]}"; do if [ -f "$dir/package.json" ]; then echo "Publishing $dir to npm…" - cd "$dir" - [ -d dist ] || pnpm run build - npm publish --access public || echo "npm publish failed for $dir" - cd - >/dev/null + ( cd "$dir" + [ -d dist ] || pnpm run build + npm publish --access public + ) fi done - - diff --git a/.github/workflows/release-web.yml b/.github/workflows/release-web.yml index 082d104b..2d301caf 100644 --- a/.github/workflows/release-web.yml +++ b/.github/workflows/release-web.yml @@ -30,38 +30,11 @@ jobs: release-web: runs-on: ubuntu-latest steps: - - name: Checkout Code + - name: Checkout code uses: actions/checkout@v4 with: - # For manual runs, allow building a chosen ref (branch/tag/SHA) ref: ${{ inputs.ref != '' && inputs.ref || github.ref }} - - name: Determine tag & latest flag - id: meta - shell: bash - run: | - # Determine TAG - if [ "${{ github.event_name }}" = "release" ]; then - TAG="${{ github.event.release.tag_name }}" - # Push "latest" only for full releases (not prereleases) - if [ "${{ github.event.release.prerelease }}" = "true" ]; then - PUSH_LATEST="false" - else - PUSH_LATEST="true" - fi - elif [ -n "${{ inputs.tag_name }}" ]; then - TAG="${{ inputs.tag_name }}" - PUSH_LATEST="false" - else - SHA="$(git rev-parse --short=12 HEAD)" - TAG="adhoc-${SHA}" - PUSH_LATEST="false" - fi - - echo "tag=$TAG" >> "$GITHUB_OUTPUT" - echo "push_latest=$PUSH_LATEST" >> "$GITHUB_OUTPUT" - echo "Resolved tag: $TAG (push_latest=$PUSH_LATEST)" - - name: Setup pnpm uses: pnpm/action-setup@v4 with: @@ -81,63 +54,62 @@ jobs: working-directory: packages/web run: pnpm run build - - name: Create Web App Release Archive + - name: Create release archive working-directory: packages/web run: pnpm run package - - name: Upload Web App Archive (artifact) + - name: Upload archive (artifact) uses: actions/upload-artifact@v4 with: - name: web-build-${{ steps.meta.outputs.tag }} - if-no-files-found: error + name: web-build path: packages/web/dist/build.tar + if-no-files-found: error - - name: Attach Web Archive to GitHub Release + - name: Attach archive to GitHub Release if: ${{ github.event_name == 'release' || inputs.attach_to_release == true }} + uses: softprops/action-gh-release@v2 + with: + files: packages/web/dist/build.tar + tag_name: ${{ github.event_name == 'release' && github.event.release.tag_name || inputs.tag_name }} + fail_on_unmatched_files: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - shell: bash - run: | - if [ "${{ github.event_name }}" = "release" ]; then - TAG="${{ steps.meta.outputs.tag }}" - else - if [ -z "${{ inputs.tag_name }}" ]; then - echo "attach_to_release requested but no tag_name provided." >&2 - exit 1 - fi - TAG="${{ inputs.tag_name }}" - fi - gh release upload "$TAG" packages/web/dist/build.tar --clobber + + - name: Docker metadata (tags & labels) + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY_IMAGE }} + tags: | + # For release events, use the release tag (e.g. v1.2.3) + type=raw,value=${{ github.event.release.tag_name }},enable=${{ github.event_name == 'release' }} + # For manual runs with a provided tag_name + type=raw,value=${{ inputs.tag_name }},enable=${{ github.event_name == 'workflow_dispatch' && inputs.tag_name != '' }} + # For manual runs without tag_name, fall back to adhoc- + type=sha,format=short,prefix=adhoc-,enable=${{ github.event_name == 'workflow_dispatch' && inputs.tag_name == '' }} + # Add "latest" only for full releases (not prereleases) + type=raw,value=latest,enable=${{ github.event_name == 'release' && github.event.release.prerelease == false }} - name: Set up QEMU uses: docker/setup-qemu-action@v3 - - name: Build Container Image - id: build-container - uses: redhat-actions/buildah-build@v2 - with: - containerfiles: | - ./packages/web/infra/Containerfile - image: ${{ env.REGISTRY_IMAGE }} - tags: latest,${{ steps.meta.outputs.tag }} - oci: true - platforms: linux/amd64,linux/arm64 + - name: Set up Buildx + uses: docker/setup-buildx-action@v3 - - name: Push Container to GHCR - id: push-to-registry - if: ${{ github.event_name == 'release' && github.event.release.prerelease == false }} - uses: redhat-actions/push-to-registry@v2 + - name: Build and (maybe) push image + uses: docker/build-push-action@v6 with: - image: ${{ steps.build-container.outputs.image }} - tags: ${{ steps.build-container.outputs.tags }} - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + context: . + file: ./packages/web/infra/Containerfile + platforms: linux/amd64,linux/arm64 + push: ${{ github.event_name == 'release' && github.event.release.prerelease == false }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} - - name: Output Image URL + - name: Output image refs if: ${{ github.event_name == 'release' && github.event.release.prerelease == false }} - run: echo "🖼️ Image pushed to ${{ steps.push-to-registry.outputs.registry-paths }}" + run: "echo \"🖼️ Pushed: ${{ steps.meta.outputs.tags }}\"" - - name: Explain no image URL + - name: Explain no image push if: ${{ !(github.event_name == 'release' && github.event.release.prerelease == false) }} - run: echo "ℹ️ No image pushed (this was a prerelease or manual run)." \ No newline at end of file + run: echo "ℹ️ No image pushed (prerelease or manual run)." diff --git a/packages/core/package.json b/packages/core/package.json index bb27fd77..fced8bb1 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -6,9 +6,9 @@ ".": "./mod.ts" }, "type": "module", - "main": "./dist/mod.mjs", - "module": "./dist/mod.mjs", - "types": "./dist/mod.d.mts", + "main": "./dist/mod.js", + "module": "./dist/mod.js", + "types": "./dist/mod.d.ts", "license": "GPL-3.0-only", "tsdown": { "entry": "mod.ts", diff --git a/packages/transport-deno/package.json b/packages/transport-deno/package.json index 52a2e136..601c8e21 100644 --- a/packages/transport-deno/package.json +++ b/packages/transport-deno/package.json @@ -5,9 +5,9 @@ "exports": { ".": "./mod.ts" }, - "main": "./dist/mod.mjs", - "module": "./dist/mod.mjs", - "types": "./dist/mod.d.mts", + "main": "./dist/mod.js", + "module": "./dist/mod.js", + "types": "./dist/mod.d.ts", "license": "GPL-3.0-only", "tsdown": { "entry": "mod.ts", diff --git a/packages/transport-http/package.json b/packages/transport-http/package.json index 6f1e8ce4..36af2c0f 100644 --- a/packages/transport-http/package.json +++ b/packages/transport-http/package.json @@ -12,9 +12,9 @@ "LICENSE", "dist" ], - "main": "./dist/mod.mjs", - "module": "./dist/mod.mjs", - "types": "./dist/mod.d.mts", + "main": "./dist/mod.js", + "module": "./dist/mod.js", + "types": "./dist/mod.d.ts", "license": "GPL-3.0-only", "tsdown": { "entry": "mod.ts", diff --git a/packages/transport-node-serial/package.json b/packages/transport-node-serial/package.json index 684559fd..35be2a18 100644 --- a/packages/transport-node-serial/package.json +++ b/packages/transport-node-serial/package.json @@ -3,12 +3,18 @@ "version": "0.0.1", "description": "NodeJS-specific serial transport layer for Meshtastic web applications.", "exports": { - ".": "./dist/mod.mjs" + ".": "./mod.ts" }, - "main": "./dist/mod.mjs", - "module": "./dist/mod.mjs", - "types": "./dist/mod.d.mts", - + "type": "module", + "main": "./dist/mod.js", + "module": "./dist/mod.js", + "types": "./dist/mod.d.ts", + "files": [ + "package.json", + "README.md", + "LICENSE", + "dist" + ], "license": "GPL-3.0-only", "tsdown": { "entry": "mod.ts", @@ -19,12 +25,6 @@ "splitting": false, "clean": true }, - "files": [ - "package.json", - "README.md", - "LICENSE", - "dist" - ], "scripts": { "preinstall": "npx only-allow pnpm", "prepack": "cp ../../LICENSE ./LICENSE", diff --git a/packages/transport-node/package.json b/packages/transport-node/package.json index 5c2776d8..e2eff7ec 100644 --- a/packages/transport-node/package.json +++ b/packages/transport-node/package.json @@ -6,9 +6,9 @@ ".": "./mod.ts" }, "type": "module", - "main": "./dist/mod.mjs", - "module": "./dist/mod.mjs", - "types": "./dist/mod.d.mts", + "main": "./dist/mod.js", + "module": "./dist/mod.js", + "types": "./dist/mod.d.ts", "license": "GPL-3.0-only", "tsdown": { diff --git a/packages/transport-web-bluetooth/package.json b/packages/transport-web-bluetooth/package.json index b4c27c66..67273014 100644 --- a/packages/transport-web-bluetooth/package.json +++ b/packages/transport-web-bluetooth/package.json @@ -6,9 +6,9 @@ ".": "./mod.ts" }, "type": "module", - "main": "./dist/mod.mjs", - "module": "./dist/mod.mjs", - "types": "./dist/mod.d.mts", + "main": "./dist/mod.js", + "module": "./dist/mod.js", + "types": "./dist/mod.d.ts", "files": [ "package.json", "README.md", diff --git a/packages/transport-web-serial/package.json b/packages/transport-web-serial/package.json index 50e28e05..ce0ff55c 100644 --- a/packages/transport-web-serial/package.json +++ b/packages/transport-web-serial/package.json @@ -6,9 +6,9 @@ ".": "./mod.ts" }, "type": "module", - "main": "./dist/mod.mjs", - "module": "./dist/mod.mjs", - "types": "./dist/mod.d.mts", + "main": "./dist/mod.js", + "module": "./dist/mod.js", + "types": "./dist/mod.d.ts", "files": [ "package.json", "README.md", diff --git a/packages/web/infra/Containerfile b/packages/web/infra/Containerfile index 1a982c22..955c3a69 100644 --- a/packages/web/infra/Containerfile +++ b/packages/web/infra/Containerfile @@ -1,4 +1,4 @@ -FROM nginx:1.27-alpine +FROM nginx:1.29.1-alpine-slim RUN rm -r /usr/share/nginx/html \ && mkdir -p /usr/share/nginx/html \ @@ -6,9 +6,9 @@ RUN rm -r /usr/share/nginx/html \ WORKDIR /usr/share/nginx/html -ADD ./dist . +ADD ./packages/web/dist . -COPY ./infra/default.conf /etc/nginx/conf.d/default.conf +COPY ./packages/web/infra/default.conf /etc/nginx/conf.d/default.conf EXPOSE 8080