diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index bcf77fb..bdd370d 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -254,14 +254,13 @@ jobs: if: failure() run: cat /tmp/mcplocal.log || true - # ── Build & package (both amd64 and arm64) ────────────── + # ── Build & package (both amd64 and arm64 sequentially) ── + # Single job builds both arches — the act runner on NAS can't handle + # matrix jobs reliably (single-worker, concurrent jobs fail). build: runs-on: ubuntu-latest needs: [lint, typecheck, test] - strategy: - matrix: - arch: [amd64, arm64] steps: - uses: actions/checkout@v4 @@ -290,56 +289,49 @@ jobs: - name: Install nfpm run: | - # nfpm itself runs on the CI runner (always x86_64); it cross-packages - # for the target arch via NFPM_ARCH env var — no ARM nfpm binary needed. curl -sL -o /tmp/nfpm.tar.gz "https://github.com/goreleaser/nfpm/releases/download/v2.45.0/nfpm_2.45.0_Linux_x86_64.tar.gz" tar xzf /tmp/nfpm.tar.gz -C /usr/local/bin nfpm - - name: Bundle standalone binaries (${{ matrix.arch }}) - env: - MCPCTL_TARGET_ARCH: ${{ matrix.arch }} + - name: Prepare bun stubs run: | - source scripts/arch-helper.sh - resolve_arch "$MCPCTL_TARGET_ARCH" - - mkdir -p dist # Stub for optional dep that Ink tries to import (only used when DEV=true) # Copy instead of symlink — bun can't read directory symlinks if [ ! -e node_modules/react-devtools-core/package.json ]; then rm -rf node_modules/react-devtools-core cp -r src/cli/stubs/react-devtools-core node_modules/react-devtools-core fi - bun build src/cli/src/index.ts --compile ${BUN_TARGET:+--target "$BUN_TARGET"} --outfile dist/mcpctl - bun build src/mcplocal/src/main.ts --compile ${BUN_TARGET:+--target "$BUN_TARGET"} --outfile dist/mcpctl-local - - name: Package RPM (${{ matrix.arch }}) - env: - NFPM_ARCH: ${{ matrix.arch }} + - name: Bundle and package (amd64) run: | - echo "Packaging RPM for arch: $NFPM_ARCH" - nfpm pkg --packager rpm --target dist/ - ls -la dist/mcpctl-*.rpm + source scripts/arch-helper.sh + resolve_arch "amd64" + mkdir -p dist + bun build src/cli/src/index.ts --compile --outfile dist/mcpctl + bun build src/mcplocal/src/main.ts --compile --outfile dist/mcpctl-local + echo "==> Packaging amd64..." + NFPM_ARCH=amd64 nfpm pkg --packager rpm --target dist/ + NFPM_ARCH=amd64 nfpm pkg --packager deb --target dist/ + ls -la dist/mcpctl-*.rpm dist/mcpctl*.deb - - name: Package DEB (${{ matrix.arch }}) - env: - NFPM_ARCH: ${{ matrix.arch }} + - name: Bundle and package (arm64) run: | - echo "Packaging DEB for arch: $NFPM_ARCH" - nfpm pkg --packager deb --target dist/ - ls -la dist/mcpctl*.deb + source scripts/arch-helper.sh + resolve_arch "arm64" + rm -f dist/mcpctl dist/mcpctl-local + bun build src/cli/src/index.ts --compile --target bun-linux-arm64 --outfile dist/mcpctl + bun build src/mcplocal/src/main.ts --compile --target bun-linux-arm64 --outfile dist/mcpctl-local + echo "==> Packaging arm64..." + NFPM_ARCH=arm64 nfpm pkg --packager rpm --target dist/ + NFPM_ARCH=arm64 nfpm pkg --packager deb --target dist/ + ls -la dist/mcpctl-*.rpm dist/mcpctl*.deb - - name: Upload RPM artifact + - name: Upload artifacts uses: actions/upload-artifact@v3 with: - name: rpm-package-${{ matrix.arch }} - path: dist/mcpctl-*.rpm - retention-days: 7 - - - name: Upload DEB artifact - uses: actions/upload-artifact@v3 - with: - name: deb-package-${{ matrix.arch }} - path: dist/mcpctl*.deb + name: packages + path: | + dist/mcpctl-*.rpm + dist/mcpctl*.deb retention-days: 7 # ── Release pipeline (main branch push only) ────────────── @@ -348,109 +340,77 @@ jobs: # needed for container-in-container builds (no /proc/self/uid_map, # no Docker socket access, buildah/podman/kaniko all fail). - publish-rpm: + publish: runs-on: ubuntu-latest needs: [build, smoke] if: github.ref == 'refs/heads/main' && github.event_name == 'push' - strategy: - matrix: - arch: [amd64, arm64] steps: - uses: actions/checkout@v4 - - name: Download RPM artifact + - name: Download package artifacts uses: actions/download-artifact@v3 with: - name: rpm-package-${{ matrix.arch }} + name: packages path: dist/ - - name: Install rpm tools - run: sudo apt-get update && sudo apt-get install -y rpm + - name: List packages + run: ls -la dist/ - - name: Publish RPM (${{ matrix.arch }}) to Gitea + - name: Publish RPMs to Gitea env: GITEA_TOKEN: ${{ secrets.PACKAGES_TOKEN }} GITEA_URL: http://${{ env.GITEA_REGISTRY }} GITEA_OWNER: ${{ env.GITEA_OWNER }} - GITEA_REPO: mcpctl run: | - RPM_FILE=$(ls dist/mcpctl-*.rpm | head -1) - echo "Publishing $RPM_FILE..." + for RPM_FILE in dist/mcpctl-*.rpm; do + echo "Publishing $RPM_FILE..." + HTTP_CODE=$(curl -s -o /tmp/rpm-upload.out -w "%{http_code}" \ + -X PUT \ + -H "Authorization: token ${GITEA_TOKEN}" \ + --upload-file "$RPM_FILE" \ + "${GITEA_URL}/api/packages/${GITEA_OWNER}/rpm/upload") - # Upload — don't delete existing packages, Gitea supports - # multiple architectures under the same version. - HTTP_CODE=$(curl -s -o /tmp/rpm-upload.out -w "%{http_code}" \ - -X PUT \ - -H "Authorization: token ${GITEA_TOKEN}" \ - --upload-file "$RPM_FILE" \ - "${GITEA_URL}/api/packages/${GITEA_OWNER}/rpm/upload") + if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "200" ]; then + echo " Published!" + elif [ "$HTTP_CODE" = "409" ]; then + echo " Already exists, skipping" + else + echo " Upload returned HTTP $HTTP_CODE" + cat /tmp/rpm-upload.out 2>/dev/null || true + exit 1 + fi + rm -f /tmp/rpm-upload.out + done - if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "200" ]; then - echo "Published successfully!" - elif [ "$HTTP_CODE" = "409" ]; then - echo "Already exists (same arch+version), skipping" - else - echo "Upload returned HTTP $HTTP_CODE" - cat /tmp/rpm-upload.out 2>/dev/null || true - exit 1 - fi - rm -f /tmp/rpm-upload.out - - # Link package to repo source scripts/link-package.sh link_package "rpm" "mcpctl" - publish-deb: - runs-on: ubuntu-latest - needs: [build, smoke] - if: github.ref == 'refs/heads/main' && github.event_name == 'push' - strategy: - matrix: - arch: [amd64, arm64] - steps: - - uses: actions/checkout@v4 - - - name: Download DEB artifact - uses: actions/download-artifact@v3 - with: - name: deb-package-${{ matrix.arch }} - path: dist/ - - - name: Publish DEB (${{ matrix.arch }}) to Gitea + - name: Publish DEBs to Gitea env: GITEA_TOKEN: ${{ secrets.PACKAGES_TOKEN }} GITEA_URL: http://${{ env.GITEA_REGISTRY }} GITEA_OWNER: ${{ env.GITEA_OWNER }} - GITEA_REPO: mcpctl run: | - DEB_FILE=$(ls dist/mcpctl*.deb | head -1) - DEB_VERSION=$(dpkg-deb --field "$DEB_FILE" Version) - echo "Publishing $DEB_FILE (version $DEB_VERSION)..." - - # Publish to each supported distribution - # Debian: trixie (13/stable), forky (14/testing) - # Ubuntu: noble (24.04 LTS), plucky (25.04) DISTRIBUTIONS="trixie forky noble plucky" - for DIST in $DISTRIBUTIONS; do - echo " -> $DIST..." - HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \ - -X PUT \ - -H "Authorization: token ${GITEA_TOKEN}" \ - --upload-file "$DEB_FILE" \ - "${GITEA_URL}/api/packages/${GITEA_OWNER}/debian/pool/${DIST}/main/upload") + for DEB_FILE in dist/mcpctl*.deb; do + echo "Publishing $DEB_FILE..." + for DIST in $DISTRIBUTIONS; do + HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \ + -X PUT \ + -H "Authorization: token ${GITEA_TOKEN}" \ + --upload-file "$DEB_FILE" \ + "${GITEA_URL}/api/packages/${GITEA_OWNER}/debian/pool/${DIST}/main/upload") - if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "200" ]; then - echo " Published to $DIST" - elif [ "$HTTP_CODE" = "409" ]; then - echo " Already exists in $DIST (skipping)" - else - echo " WARNING: Upload to $DIST returned HTTP $HTTP_CODE" - fi + if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "200" ]; then + echo " -> $DIST: published" + elif [ "$HTTP_CODE" = "409" ]; then + echo " -> $DIST: already exists" + else + echo " -> $DIST: HTTP $HTTP_CODE (warning)" + fi + done done - echo "Published successfully!" - - # Link package to repo source scripts/link-package.sh link_package "debian" "mcpctl"