Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 1 addition & 61 deletions .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
name: Build and Push Docker Image
name: Pull request checks

on:
push:
branches:
- main
tags:
- 'v*'
pull_request:
branches:
- main
workflow_dispatch:
Comment on lines 3 to 7

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
test-and-analyze:
name: Test and analyze
Expand Down Expand Up @@ -51,54 +42,3 @@ jobs:
git --no-pager diff -- public/openapi.json
exit 1
fi
build-docker-push:
needs: test-and-analyze
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0

- name: Read version from package.json
id: pkg
run: echo "version=$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT"

- name: Log in to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,value=${{ steps.pkg.outputs.version }},enable={{is_default_branch}}
type=sha,prefix=main-,enable={{is_default_branch}}
type=sha,prefix={{branch}}-,enable=${{ github.event_name == 'push' && !startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/main' }}
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and push Docker image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
6 changes: 6 additions & 0 deletions .johnaverse/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: 1
versionFile: package.json
images:
- name: chains-api
context: .
dockerfile: Dockerfile
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "chains-api",
"version": "1.7.35",
"version": "1.7.36",
"description": "API query service for blockchain chain data from multiple sources",
"main": "index.js",
"type": "module",
Expand Down
2 changes: 1 addition & 1 deletion public/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"info": {
"title": "Chains API",
"description": "Aggregated blockchain chain data from five external sources (TheGraph, Chainlist, Chain ID Network, SLIP-0044, L2BEAT): chain metadata, relations, RPC endpoints and health, L2 scaling, and operator status.",
"version": "1.7.35"
"version": "1.7.36"
},
"components": {
"schemas": {}
Expand Down
20 changes: 10 additions & 10 deletions tests/unit/services/forks.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('getForks', () => {

it('groups a fork across sources and reports where it came from', async () => {
getLiveEvents.mockResolvedValue([
event('a', { fork: fork({ name: 'Protocol 28', activationAt: '2026-09-16T17:00:00Z' }), affectedChains: ['Stellar Mainnet'], page: 'xlm' }),
event('a', { fork: fork({ name: 'Protocol 28', activationAt: '2099-09-16T17:00:00Z' }), affectedChains: ['Stellar Mainnet'], page: 'xlm' }),
event('b', { fork: fork({ name: 'Protocol 28' }), affectedChains: ['Stellar Mainnet'], page: 'quicknode' })
]);

Expand All @@ -39,7 +39,7 @@ describe('getForks', () => {
it('does not call the explorer when every activation is already stated', async () => {
// The common case must cost no network round trip.
getLiveEvents.mockResolvedValue([
event('a', { fork: fork({ name: 'Rex6', activationAt: '2026-09-01T00:00:00Z' }), affectedChains: ['MegaETH Mainnet'] })
event('a', { fork: fork({ name: 'Rex6', activationAt: '2099-09-01T00:00:00Z' }), affectedChains: ['MegaETH Mainnet'] })
]);

await getForks();
Expand Down Expand Up @@ -78,7 +78,7 @@ describe('getForks', () => {

it('scheduledOnly drops forks with no known date — what a calendar needs', async () => {
getLiveEvents.mockResolvedValue([
event('dated', { fork: fork({ name: 'Dated', activationAt: '2026-09-01T00:00:00Z' }), affectedChains: ['A'] }),
event('dated', { fork: fork({ name: 'Dated', activationAt: '2099-09-01T00:00:00Z' }), affectedChains: ['A'] }),
event('undated', { fork: fork({ name: 'Undated' }), affectedChains: ['B'] })
]);

Expand All @@ -93,8 +93,8 @@ describe('getForks', () => {
it('counts phases over everything matched, not just the page shown', async () => {
// A caller asking "how many upcoming forks" must not have to add up a truncated list.
getLiveEvents.mockResolvedValue([
event('1', { fork: fork({ name: 'a', activationAt: '2026-09-01T00:00:00Z' }), affectedChains: ['x'] }),
event('2', { fork: fork({ name: 'b', activationAt: '2026-09-02T00:00:00Z' }), affectedChains: ['y'] }),
event('1', { fork: fork({ name: 'a', activationAt: '2099-09-01T00:00:00Z' }), affectedChains: ['x'] }),
event('2', { fork: fork({ name: 'b', activationAt: '2099-09-02T00:00:00Z' }), affectedChains: ['y'] }),
event('3', { fork: fork({ name: 'c', activationAt: '2020-01-01T00:00:00Z' }), affectedChains: ['z'] })
]);

Expand Down Expand Up @@ -126,7 +126,7 @@ describe('getForks', () => {

it('filters by chain and by phase', async () => {
getLiveEvents.mockResolvedValue([
event('1', { fork: fork({ name: 'a', activationAt: '2026-09-01T00:00:00Z' }), chains: [1] }),
event('1', { fork: fork({ name: 'a', activationAt: '2099-09-01T00:00:00Z' }), chains: [1] }),
event('2', { fork: fork({ name: 'b', activationAt: '2020-01-01T00:00:00Z' }), chains: [8453] })
]);

Expand All @@ -139,7 +139,7 @@ describe('getForks', () => {
// and the assistant — which truncates tool results at 8000 chars — would have seen two
// forks under a header reading count: 50, truncated: false.
getLiveEvents.mockResolvedValue([
event('a', { fork: fork({ name: 'Rex6', activationAt: '2026-09-01T00:00:00Z' }), affectedChains: ['MegaETH Mainnet'] })
event('a', { fork: fork({ name: 'Rex6', activationAt: '2099-09-01T00:00:00Z' }), affectedChains: ['MegaETH Mainnet'] })
]);

const out = await getForks();
Expand All @@ -155,8 +155,8 @@ describe('getForks', () => {
// `chain:8453` and `unscoped` are grouping keys. The tool description tells the model each
// fork "carries network", so emitting those put an internal identifier in an answer.
getLiveEvents.mockResolvedValue([
event('a', { fork: fork({ name: 'Rex6', activationAt: '2026-09-01T00:00:00Z' }), chains: [8453] }),
event('b', { fork: fork({ name: 'Other', activationAt: '2026-09-02T00:00:00Z' }) })
event('a', { fork: fork({ name: 'Rex6', activationAt: '2099-09-01T00:00:00Z' }), chains: [8453] }),
event('b', { fork: fork({ name: 'Other', activationAt: '2099-09-02T00:00:00Z' }) })
]);

const out = await getForks();
Expand All @@ -180,7 +180,7 @@ describe('getForks', () => {
id: 'op', title: 'OP Stack upgrade', publishedAt: '2026-08-14T00:00:00Z',
updatedAt: '2026-08-14T00:00:00Z', statusPage: { id: 'quicknode' }, chains: [],
enrichment: {
fork: fork({ name: 'Isthmus', activationAt: '2026-09-01T00:00:00Z' }),
fork: fork({ name: 'Isthmus', activationAt: '2099-09-01T00:00:00Z' }),
affectedChains: ['OP Mainnet'],
chains: [10, 8453]
}
Expand Down