diff --git a/.github/workflows/auto-release-pr.yml b/.github/workflows/auto-release-pr.yml index d5828e37..f2205bb4 100644 --- a/.github/workflows/auto-release-pr.yml +++ b/.github/workflows/auto-release-pr.yml @@ -2,9 +2,9 @@ name: Auto release PR on: push: - branches: - - main - - staging + tags: + - '*' + workflow_dispatch: permissions: contents: write # to create release @@ -13,37 +13,51 @@ permissions: jobs: # from https://github.com/peter-evans/create-pull-request/blob/main/docs/examples.md#keep-a-branch-up-to-date-with-another productionRelease: - if: github.ref == 'refs/heads/staging' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: ref: production - - name: Create PR from staging to production + - name: Fetch all tags + run: git fetch --tags + - name: Get latest tag + id: get_latest_tag + run: echo "tag=$(git describe --tags `git rev-list --tags --max-count=1`)" >> $GITHUB_OUTPUT + - name: Checkout latest tag + run: git checkout ${{ steps.get_latest_tag.outputs.tag }} + - name: Ensure production-release branch points to latest tag run: | - git fetch origin main:main - git reset --hard main + git checkout -B production-release ${{ steps.get_latest_tag.outputs.tag }} + git push origin production-release --force - name: Create Pull Request - uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5 + uses: peter-evans/create-pull-request@v7.0.5 with: + base: production branch: production-release - title: 'chore: Merge staging into production' - body: 'This PR merges commits from staging into production.' + title: 'chore: Point production to release ${{ steps.get_latest_tag.outputs.tag }}' + body: 'This PR points the production branch to release ${{ steps.get_latest_tag.outputs.tag }}.' stagingRelease: - if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: ref: staging - - name: Create PR from main to staging + - name: Fetch all tags + run: git fetch --tags + - name: Get latest tag + id: get_latest_tag + run: echo "tag=$(git describe --tags `git rev-list --tags --max-count=1`)" >> $GITHUB_OUTPUT + - name: Checkout latest tag + run: git checkout ${{ steps.get_latest_tag.outputs.tag }} + - name: Ensure staging-release branch points to latest tag run: | - git fetch origin main:main - git reset --hard main + git checkout -B staging-release ${{ steps.get_latest_tag.outputs.tag }} + git push origin staging-release --force - name: Create Pull Request - uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5 + uses: peter-evans/create-pull-request@v7.0.5 with: + base: staging branch: staging-release - title: 'chore: Merge main into staging' - body: 'This PR merges commits from main into staging.' + title: 'chore: point staging to release ${{ steps.get_latest_tag.outputs.tag }}' + body: 'This PR points the staging branch to release ${{ steps.get_latest_tag.outputs.tag }}.' diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e2340a2..3522275c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## [1.6.0](https://github.com/ipfs/service-worker-gateway/compare/v1.5.0...v1.6.0) (2024-11-11) + + +### Features + +* delegated routing request deduplication and caching ([90c48a0](https://github.com/ipfs/service-worker-gateway/commit/90c48a070e2316bb83bf97400c9ae07d8ac4acc8)) + +## [1.5.0](https://github.com/ipfs/service-worker-gateway/compare/v1.4.1...v1.5.0) (2024-11-05) + + +### Features + +* add blake3 hasher ([#421](https://github.com/ipfs/service-worker-gateway/issues/421)) ([6270acd](https://github.com/ipfs/service-worker-gateway/commit/6270acd2696417afe2b61803278f461636c3a69a)) + + +### Bug Fixes + +* apply dns resolvers corectly ([#412](https://github.com/ipfs/service-worker-gateway/issues/412)) ([ba0ede9](https://github.com/ipfs/service-worker-gateway/commit/ba0ede9f3c050f20adf5cd391818d332e9b301b8)) +* force use of latest multiaddr-to-uri ([#409](https://github.com/ipfs/service-worker-gateway/issues/409)) ([4915b34](https://github.com/ipfs/service-worker-gateway/commit/4915b346cb64514e47102de32aec74a88e67cd5e)) + ## [1.4.1](https://github.com/ipfs/service-worker-gateway/compare/v1.4.0...v1.4.1) (2024-10-25) diff --git a/package-lock.json b/package-lock.json index def6f740..cfed96d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,19 @@ { "name": "helia-service-worker-gateway", - "version": "1.4.1", + "version": "1.6.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "helia-service-worker-gateway", - "version": "1.4.1", + "version": "1.6.0", "hasInstallScript": true, "license": "MIT", "dependencies": { "@chainsafe/libp2p-noise": "^16.0.0", "@chainsafe/libp2p-yamux": "^7.0.1", "@helia/block-brokers": "^4.0.1", - "@helia/delegated-routing-v1-http-api-client": "^4.1.1", + "@helia/delegated-routing-v1-http-api-client": "^4.2.0", "@helia/http": "^2.0.1", "@helia/interface": "^5.0.0", "@helia/routers": "^2.1.0", @@ -27,11 +27,12 @@ "@libp2p/websockets": "^9.0.11", "@libp2p/webtransport": "^5.0.16", "@multiformats/dns": "^1.0.6", + "@noble/hashes": "^1.5.0", "@sgtpooki/file-type": "^1.0.1", "helia": "^5.1.0", "ipfs-css": "^1.4.0", "libp2p": "^2.2.1", - "multiformats": "^13.1.0", + "multiformats": "^13.3.1", "react": "^18.3.0", "react-dom": "^18.3.1", "tachyons": "^4.12.0" @@ -51,12 +52,12 @@ "glob": "^10.3.12", "http-server": "^14.1.1", "ipfsd-ctl": "^13.0.0", - "kubo": "^0.27.0", + "kubo": "^0.31.0", "kubo-rpc-client": "^5.0.2", "npm-run-all": "^4.1.5", "patch-package": "^8.0.0", "playwright": "^1.45.3", - "rimraf": "^5.0.5" + "rimraf": "^6.0.1" } }, "node_modules/@achingbrain/nat-port-mapper": { @@ -2951,11 +2952,11 @@ } }, "node_modules/@helia/delegated-routing-v1-http-api-client": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@helia/delegated-routing-v1-http-api-client/-/delegated-routing-v1-http-api-client-4.1.1.tgz", - "integrity": "sha512-Pf5pZkZGEBhARFXoLRzVVSZ8E8yU0Q0F3DOadhxPQjaSNyahetwiTsV8TvJltfrs2Afy2+gbA2+Rycl7apSXdQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@helia/delegated-routing-v1-http-api-client/-/delegated-routing-v1-http-api-client-4.2.0.tgz", + "integrity": "sha512-2lIL9SyR72yINUIRac5SkY7obMbylEringExSV1t13oM7MjuU+NziCkJr/uU/d3EWwR53fafNsZf8wizQqe8bA==", "dependencies": { - "@libp2p/interface": "^2.0.1", + "@libp2p/interface": "^2.2.0", "@libp2p/logger": "^5.0.1", "@libp2p/peer-id": "^5.0.1", "@multiformats/multiaddr": "^12.3.1", @@ -4282,6 +4283,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", + "license": "MIT", "engines": { "node": "^14.21.3 || >=16" }, @@ -8694,6 +8696,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/aegir/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "dev": true, + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/aegir/node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -18204,9 +18221,9 @@ } }, "node_modules/kubo": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/kubo/-/kubo-0.27.0.tgz", - "integrity": "sha512-mcl9Jh8ihg8reMxPCwKvUvHJyRV1ouMHApPS+/WK9jOyFs7ke8E/JI1eMwBp95BqgzsjdEGJESwRjNGGTxkR/A==", + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/kubo/-/kubo-0.31.0.tgz", + "integrity": "sha512-3he8THK76gyYkVNnHpTo4LnMl/5fpZjNnaepCn2IKO+R5GXjLPvzydj+WJhyRuPT19H1c/tBW3COF03IXCO4lQ==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -21260,9 +21277,9 @@ } }, "node_modules/multiformats": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-13.3.0.tgz", - "integrity": "sha512-CBiqvsufgmpo01VT5ze94O+uc+Pbf6f/sThlvWss0sBZmAOu6GQn5usrYV2sf2mr17FWYc0rO8c/CNe2T90QAA==" + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-13.3.1.tgz", + "integrity": "sha512-QxowxTNwJ3r5RMctoGA5p13w5RbRT2QDkoM+yFlqfLiioBp78nhDjnRLvmSBI9+KAqN4VdgOVWM9c0CHd86m3g==" }, "node_modules/multimatch": { "version": "5.0.0", @@ -29797,16 +29814,98 @@ } }, "node_modules/rimraf": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", - "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", + "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", "dev": true, "dependencies": { - "glob": "^10.3.7" + "glob": "^11.0.0", + "package-json-from-dist": "^1.0.0" }, "bin": { "rimraf": "dist/esm/bin.mjs" }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/jackspeak": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", + "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/lru-cache": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", + "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==", + "dev": true, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dev": true, + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, "funding": { "url": "https://github.com/sponsors/isaacs" } diff --git a/package.json b/package.json index 0c388f57..43b4fa06 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "helia-service-worker-gateway", - "version": "1.4.1", + "version": "1.6.0", "private": true, "type": "module", "description": "An IPFS Gateway that uses @helia/verified-fetch in a Service Worker to fetch content", @@ -42,7 +42,7 @@ "@chainsafe/libp2p-noise": "^16.0.0", "@chainsafe/libp2p-yamux": "^7.0.1", "@helia/block-brokers": "^4.0.1", - "@helia/delegated-routing-v1-http-api-client": "^4.1.1", + "@helia/delegated-routing-v1-http-api-client": "^4.2.0", "@helia/http": "^2.0.1", "@helia/interface": "^5.0.0", "@helia/routers": "^2.1.0", @@ -56,11 +56,12 @@ "@libp2p/websockets": "^9.0.11", "@libp2p/webtransport": "^5.0.16", "@multiformats/dns": "^1.0.6", + "@noble/hashes": "^1.5.0", "@sgtpooki/file-type": "^1.0.1", "helia": "^5.1.0", "ipfs-css": "^1.4.0", "libp2p": "^2.2.1", - "multiformats": "^13.1.0", + "multiformats": "^13.3.1", "react": "^18.3.0", "react-dom": "^18.3.1", "tachyons": "^4.12.0" @@ -80,12 +81,12 @@ "glob": "^10.3.12", "http-server": "^14.1.1", "ipfsd-ctl": "^13.0.0", - "kubo": "^0.27.0", + "kubo": "^0.31.0", "kubo-rpc-client": "^5.0.2", "npm-run-all": "^4.1.5", "patch-package": "^8.0.0", "playwright": "^1.45.3", - "rimraf": "^5.0.5" + "rimraf": "^6.0.1" }, "sideEffects": [ "*.css" diff --git a/src/lib/blake3.ts b/src/lib/blake3.ts new file mode 100644 index 00000000..9e1e3ad7 --- /dev/null +++ b/src/lib/blake3.ts @@ -0,0 +1,8 @@ +import { blake3 as b3 } from '@noble/hashes/blake3' +import { from } from 'multiformats/hashes/hasher' + +export const blake3 = from({ + name: 'blake3', + code: 0x1e, // Code for blake3 from https://github.com/multiformats/multicodec/blob/352d05ad430713088e867216152725f581387bc8/table.csv#L21 + encode: (input) => b3(input) +}) diff --git a/src/lib/get-verified-fetch.ts b/src/lib/get-verified-fetch.ts index 2df12790..5cb6f805 100644 --- a/src/lib/get-verified-fetch.ts +++ b/src/lib/get-verified-fetch.ts @@ -18,6 +18,7 @@ import { dnsJsonOverHttps } from '@multiformats/dns/resolvers' import { createHelia, type Helia, type Routing } from 'helia' import { createLibp2p, type Libp2pOptions } from 'libp2p' import * as libp2pInfo from 'libp2p/version' +import { blake3 } from './blake3.js' import { contentTypeParser } from './content-type-parser.js' import type { ConfigDb } from './config-db.js' import type { ComponentLogger } from '@libp2p/logger' @@ -52,6 +53,8 @@ export async function getVerifiedFetch (config: ConfigDb, logger: ComponentLogge blockBrokers.push(trustlessGateway()) } + const hashers = [blake3] + let helia: Helia if (config.enableWss || config.enableWebTransport) { // If we are using websocket or webtransport, we need to instantiate libp2p @@ -65,6 +68,7 @@ export async function getVerifiedFetch (config: ConfigDb, logger: ComponentLogge libp2p, routers, blockBrokers, + hashers, dns: dnsConfig }) } else { @@ -81,6 +85,7 @@ export async function getVerifiedFetch (config: ConfigDb, logger: ComponentLogge helia = await createHeliaHTTP({ routers, blockBrokers, + hashers, dns: dnsConfig }) }