Skip to content

Commit bdac63e

Browse files
author
Darren Kelly
committed
Merge branch 'master' into release/hayabusa
2 parents 8343809 + b01ac99 commit bdac63e

17 files changed

Lines changed: 438 additions & 51 deletions

.github/workflows/on-master-commit.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ jobs:
3737
contents: read
3838
secrets: inherit
3939

40+
run-smoke-tests:
41+
name: Smoke Tests
42+
uses: ./.github/workflows/test-smoke.yaml
43+
permissions:
44+
contents: read
45+
secrets: inherit
46+
needs: [run-e2e-tests]
47+
4048
run-rosetta-tests:
4149
name: Rosetta Tests
4250
uses: ./.github/workflows/test-rosetta.yaml

.github/workflows/on-pre-release.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,15 @@ jobs:
4141
ghcr.io/${{ github.repository }}
4242
tags: |
4343
type=raw,value=${{ github.ref_name }}
44+
45+
publish-binaries:
46+
name: Publish Binaries
47+
uses: ./.github/workflows/release-binaries.yaml
48+
secrets: inherit
49+
needs:
50+
- validate
51+
permissions:
52+
contents: write
53+
54+
with:
55+
binary: 'thor'

.github/workflows/on-pull-request.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ jobs:
3333
contents: read
3434
secrets: inherit
3535

36+
run-smoke-tests:
37+
name: Smoke Tests
38+
uses: ./.github/workflows/test-smoke.yaml
39+
permissions:
40+
contents: read
41+
secrets: inherit
42+
needs: [run-e2e-tests]
43+
3644
run-rosetta-tests:
3745
name: Rosetta Tests
3846
uses: ./.github/workflows/test-rosetta.yaml

.github/workflows/on-release.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,15 @@ jobs:
7070
tags: |
7171
type=raw,value=${{ github.ref_name }}
7272
type=raw,value=latest
73+
74+
publish-binaries:
75+
name: Publish Binaries
76+
uses: ./.github/workflows/release-binaries.yaml
77+
secrets: inherit
78+
needs:
79+
- validate
80+
permissions:
81+
contents: write
82+
packages: write
83+
with:
84+
binary: 'thor'
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
name: Release Binaries
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
binary:
7+
options:
8+
- thor
9+
- disco
10+
description: 'Select the binary to build and release'
11+
type: choice
12+
required: true
13+
default: thor
14+
workflow_call:
15+
inputs:
16+
binary:
17+
description: 'Select the binary to build and release'
18+
type: string
19+
required: true
20+
default: thor
21+
22+
permissions:
23+
contents: write
24+
packages: write
25+
26+
jobs:
27+
build-unix:
28+
name: Build Linux/macOS binaries
29+
runs-on: ${{ matrix.hostos }}
30+
strategy:
31+
matrix:
32+
include:
33+
- goos: linux
34+
goarch: amd64
35+
hostos: ubuntu-latest
36+
- goos: linux
37+
goarch: arm64
38+
hostos: ubuntu-24.04-arm
39+
- goos: darwin
40+
goarch: arm64
41+
hostos: macos-latest
42+
env:
43+
BINARY: ${{ inputs.binary || 'thor' }}
44+
RELEASE_BINARY_NAME: ./dist/${{ inputs.binary || 'thor' }}-${{ matrix.goos }}-${{ matrix.goarch }}
45+
ARCHIVE_NAME: ./dist/${{ inputs.binary || 'thor' }}-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz
46+
47+
environment: binary-publish
48+
steps:
49+
- uses: actions/checkout@v5
50+
with:
51+
fetch-depth: 0
52+
53+
- uses: actions/setup-go@v5
54+
with:
55+
go-version: 1.24
56+
57+
- name: Build Binary
58+
shell: bash
59+
run: |
60+
make $BINARY
61+
mkdir -p ./dist
62+
mv ./bin/${BINARY} $RELEASE_BINARY_NAME
63+
chmod +x $RELEASE_BINARY_NAME
64+
65+
- name: Import GPG Private Key
66+
env:
67+
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
68+
run: |
69+
echo "$GPG_PRIVATE_KEY" | gpg --batch --import
70+
71+
- name: Sign Executable with GPG
72+
env:
73+
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
74+
shell: bash
75+
run: |
76+
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" --armor --detach-sign "$RELEASE_BINARY_NAME"
77+
78+
- name: Create archive
79+
shell: bash
80+
run: |
81+
cd dist
82+
tar czf "${ARCHIVE_NAME##*/}" "$(basename "$RELEASE_BINARY_NAME")"
83+
84+
- name: Upload Binary
85+
uses: alexellis/upload-assets@0.4.1
86+
env:
87+
GITHUB_TOKEN: ${{ github.token }}
88+
with:
89+
asset_paths: '["${{env.RELEASE_BINARY_NAME}}", "${{env.ARCHIVE_NAME}}"]'
90+
91+
build-windows:
92+
name: Build Windows binary
93+
runs-on: windows-latest
94+
env:
95+
BINARY: ${{ inputs.binary || 'thor' }}
96+
RELEASE_BINARY_NAME: ./dist/${{ inputs.binary || 'thor' }}-windows-amd64.exe
97+
ARCHIVE_NAME: ./dist/${{ inputs.binary || 'thor' }}-windows-amd64.zip
98+
environment: binary-publish
99+
steps:
100+
- uses: actions/checkout@v5
101+
with:
102+
fetch-depth: 0
103+
104+
- uses: actions/setup-go@v5
105+
with:
106+
go-version: 1.24
107+
108+
- name: Build Binary
109+
shell: pwsh
110+
run: |
111+
make $Env:BINARY
112+
New-Item -ItemType Directory -Force -Path ./dist | Out-Null
113+
Move-Item -Force "./bin/$Env:BINARY" $Env:RELEASE_BINARY_NAME
114+
115+
- name: Import GPG Private Key
116+
shell: pwsh
117+
env:
118+
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
119+
run: |
120+
$gpgKey = $Env:GPG_PRIVATE_KEY -replace "`r`n", "`n"
121+
$gpgKey | Out-File -Encoding ascii private.key
122+
gpg --batch --import private.key
123+
124+
- name: Sign Executable with GPG
125+
shell: pwsh
126+
env:
127+
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
128+
run: |
129+
gpg --batch --yes --pinentry-mode loopback --passphrase "$Env:GPG_PASSPHRASE" --armor --detach-sign "$Env:RELEASE_BINARY_NAME"
130+
131+
- name: Create archive
132+
shell: pwsh
133+
run: |
134+
Set-Location ./dist
135+
Compress-Archive -Path (Split-Path -Leaf $Env:RELEASE_BINARY_NAME) -DestinationPath (Split-Path -Leaf $Env:ARCHIVE_NAME)
136+
137+
- name: Upload Binary
138+
uses: alexellis/upload-assets@0.4.1
139+
env:
140+
GITHUB_TOKEN: ${{ github.token }}
141+
with:
142+
asset_paths: '["${{env.RELEASE_BINARY_NAME}}", "${{env.ARCHIVE_NAME}}"]'

.github/workflows/test-smoke.yaml

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
name: Smoke Tests
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
draupnir-branch:
7+
type: string
8+
default: 'main'
9+
10+
permissions:
11+
contents: read
12+
13+
jobs:
14+
build-docker-image:
15+
name: Build Docker image
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Checkout
19+
uses: actions/checkout@v4
20+
21+
- name: Try to download e2e artifact
22+
id: download-artifact
23+
continue-on-error: true
24+
uses: actions/download-artifact@v4
25+
with:
26+
name: vechain-thor-image-${{ github.sha }}
27+
path: /tmp
28+
29+
- name: Set up QEMU
30+
if: steps.download-artifact.outcome == 'failure'
31+
uses: docker/setup-qemu-action@v3
32+
33+
- name: Set up Docker Buildx
34+
if: steps.download-artifact.outcome == 'failure'
35+
uses: docker/setup-buildx-action@v3
36+
37+
- name: Build and export
38+
if: steps.download-artifact.outcome == 'failure'
39+
uses: docker/build-push-action@v6
40+
with:
41+
context: .
42+
tags: vechain/thor:${{ github.sha }}
43+
outputs: type=docker,dest=/tmp/vechain-thor.tar
44+
45+
- name: Upload artifact
46+
if: steps.download-artifact.outcome == 'failure'
47+
uses: actions/upload-artifact@v4
48+
with:
49+
name: vechain-thor-image-${{ github.sha }}
50+
path: /tmp/vechain-thor.tar
51+
retention-days: 7
52+
53+
run-smoke-tests:
54+
runs-on: ubuntu-latest
55+
needs: build-docker-image
56+
env:
57+
THOR_IMAGE: vechain/thor:${{ github.sha }}
58+
name: Run Smoke Tests
59+
steps:
60+
- name: Set up git credentials
61+
run: |
62+
git config --global url."https://${{ secrets.DRAUPNIR_TOKEN }}@github.com/".insteadOf "https://github.com/"
63+
64+
- name: Set draupnir repo reference
65+
id: set-ref
66+
run: |
67+
# Default fallback commit
68+
DEFAULT_COMMIT="87786521c01be03d7a39cedb3b34d640f9f8632e"
69+
REF="$DEFAULT_COMMIT"
70+
71+
if [ "${{ github.event_name }}" = "pull_request" ]; then
72+
# For pull_request events, we only look at the PR's base branch
73+
if [[ "${{ github.event.pull_request.base.ref }}" == release/* ]]; then
74+
REF="${{ github.event.pull_request.base.ref }}"
75+
fi
76+
else
77+
# For push events, we check the branch or tag that was pushed
78+
if [[ "${{ github.ref_name }}" == release/* ]]; then
79+
REF="${{ github.ref_name }}"
80+
fi
81+
fi
82+
83+
# Verify if branch exists
84+
if ! git ls-remote --heads https://github.com/vechain/draupnir.git $REF; then
85+
echo "Branch does not exist, using default commit"
86+
echo "ref=$DEFAULT_COMMIT" >> "$GITHUB_OUTPUT"
87+
else
88+
echo "ref=$REF" >> "$GITHUB_OUTPUT"
89+
fi
90+
91+
echo "DRAUPNIR REF: $(<$GITHUB_OUTPUT)"
92+
93+
- name: Checkout
94+
uses: actions/checkout@v4
95+
with:
96+
repository: vechain/draupnir
97+
token: ${{ secrets.DRAUPNIR_TOKEN }}
98+
ref: ${{ steps.set-ref.outputs.ref }}
99+
100+
- name: Download artifact
101+
uses: actions/download-artifact@v4
102+
with:
103+
name: vechain-thor-image-${{ github.sha }}
104+
path: /tmp
105+
106+
- name: Load image
107+
run: |
108+
docker load --input /tmp/vechain-thor.tar
109+
docker image ls -a
110+
111+
- name: Setup Go
112+
uses: actions/setup-go@v5
113+
with:
114+
go-version: '1.24.x'
115+
116+
- name: Start Thor Node
117+
run: |
118+
docker run -d --name thor-node \
119+
--network host \
120+
-p 8669:8669 \
121+
vechain/thor:${{ github.sha }} \
122+
solo --gas-limit=40000000 --api-cors="*" --enable-metrics
123+
124+
- name: Wait for Thor to be ready
125+
run: |
126+
timeout 60 bash -c 'until curl -s http://localhost:8669/accounts; do sleep 2; done'
127+
128+
129+
- name: Run Smoke Test Separately
130+
run: |
131+
RUNTESTS=TestSmokeTest,TestGenerateRequests,TestConnectionDiesNoPingResponse,TestConnectionClosedWithoutSubscription \
132+
TEST_NETWORK_ADDR=http://127.0.0.1:8669 \
133+
TEST_PK=99f0500549792796c14fed62011a51081dc5b5e68fe8bd8a13b86be829c4fd36 \
134+
go test --count=1 -v ./tests/smoketest -run TestSmokeTest
135+
136+
- name: Cleanup
137+
if: always()
138+
run: |
139+
docker stop thor-node || true
140+
docker rm thor-node || true

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,5 @@ package.json
2929
coverage.out
3030

3131
.idea
32+
33+
dist/

api/events/events.go

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ package events
88
import (
99
"context"
1010
"fmt"
11-
"math"
1211
"net/http"
1312

1413
"github.com/gorilla/mux"
@@ -57,14 +56,11 @@ func (e *Events) handleFilter(w http.ResponseWriter, req *http.Request) error {
5756
if err := restutil.ParseJSON(req.Body, &filter); err != nil {
5857
return restutil.BadRequest(errors.WithMessage(err, "body"))
5958
}
60-
if filter.Options != nil && filter.Options.Limit > e.limit {
61-
return restutil.Forbidden(fmt.Errorf("options.limit exceeds the maximum allowed value of %d", e.limit))
59+
if err := filter.Options.Validate(e.limit); err != nil {
60+
return restutil.Forbidden(err)
6261
}
63-
if filter.Options != nil && filter.Options.Offset > math.MaxInt64 {
64-
return restutil.BadRequest(fmt.Errorf("options.offset exceeds the maximum allowed value of %d", math.MaxInt64))
65-
}
66-
if filter.Range != nil && filter.Range.From != nil && filter.Range.To != nil && *filter.Range.From > *filter.Range.To {
67-
return restutil.BadRequest(fmt.Errorf("filter.Range.To must be greater than or equal to filter.Range.From"))
62+
if err := filter.Range.Validate(); err != nil {
63+
return restutil.BadRequest(err)
6864
}
6965
// reject null element in CriteriaSet, {} will be unmarshaled to default value and will be accepted/handled by the filter engine
7066
for i, criterion := range filter.CriteriaSet {
@@ -73,13 +69,13 @@ func (e *Events) handleFilter(w http.ResponseWriter, req *http.Request) error {
7369
}
7470
}
7571
if filter.Options == nil {
76-
// if filter.Options is nil, set to the default limit +1
72+
filter.Options = &api.Options{}
73+
}
74+
if filter.Options.Limit == nil {
75+
// if filter.Options.Limit is nil, set to the default limit +1
7776
// to detect whether there are more logs than the default limit
78-
filter.Options = &api.Options{
79-
Offset: 0,
80-
Limit: e.limit + 1,
81-
IncludeIndexes: false,
82-
}
77+
limit := e.limit + 1
78+
filter.Options.Limit = &limit
8379
}
8480

8581
fes, err := e.filter(req.Context(), &filter)

0 commit comments

Comments
 (0)