diff --git a/.github/actions/test/action.yml b/.github/actions/test/action.yml index 173feef1..d6feabcc 100644 --- a/.github/actions/test/action.yml +++ b/.github/actions/test/action.yml @@ -8,7 +8,7 @@ runs: shell: bash run: git config --global core.autocrlf false - name: Lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v4 with: skip-cache: true - name: Analyze @@ -19,6 +19,6 @@ runs: directories: | api - name: Test - uses: n8maninger/action-golang-test@v1 + uses: n8maninger/action-golang-test@v2 with: args: "-race;-tags=testing netgo" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 37bd0335..4c63e7b9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,8 +20,8 @@ jobs: steps: - name: Configure git run: git config --global core.autocrlf false # required on Windows - - uses: actions/checkout@v3 - - uses: actions/setup-go@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} - name: Test diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000..a2e91506 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,261 @@ +name: Publish + +# Controls when the action will run. +on: + # Triggers the workflow on new SemVer tags + push: + branches: + - master + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + - 'v[0-9]+.[0-9]+.[0-9]+-**' + +concurrency: + group: ${{ github.workflow }} + +jobs: + test: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: '1.21' + - name: Test + uses: ./.github/actions/test + docker: + runs-on: ubuntu-latest + needs: [ test ] + permissions: + packages: write + contents: read + steps: + - uses: actions/checkout@v4 + - uses: docker/setup-qemu-action@v3 + - uses: docker/setup-buildx-action@v3 + - uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + - uses: docker/metadata-action@v5 + name: generate tags + id: meta + with: + images: ghcr.io/${{ github.repository }} + tags: | + type=ref,event=branch + type=sha,prefix= + type=semver,pattern={{version}} + - uses: docker/build-push-action@v5 + with: + context: . + file: ./docker/Dockerfile + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + cache-from: type=gha + cache-to: type=gha,mode=max + build-linux: + runs-on: ubuntu-latest + needs: [ test ] + strategy: + matrix: + go-arch: [amd64, arm64] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: '1.21' + - name: Setup + run: | + sudo apt update + go generate ./... + if [ ${{ matrix.go-arch }} == "arm64" ]; then + sudo apt install -y gcc-aarch64-linux-gnu + echo "CC=aarch64-linux-gnu-gcc" >> $GITHUB_ENV + fi + - name: Build ${{ matrix.go-arch }} + env: + CGO_ENABLED: 1 + GOOS: linux + GOARCH: ${{ matrix.go-arch }} + run: | + mkdir -p release + ZIP_OUTPUT=release/explored_${GOOS}_${GOARCH}.zip + go build -tags='netgo' -trimpath -o bin/ -a -ldflags '-s -w -linkmode external -extldflags "-static"' ./cmd/explored + cp README.md LICENSE bin/ + zip -qj $ZIP_OUTPUT bin/* + - uses: actions/upload-artifact@v4 + with: + name: explored_linux_${{ matrix.go-arch }} + path: release/* + build-mac: + runs-on: macos-latest + needs: [ test ] + strategy: + matrix: + go-arch: [amd64, arm64] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: '1.21' + - name: Setup + env: + APPLE_CERT_ID: ${{ secrets.APPLE_CERT_ID }} + APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }} + APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }} + APPLE_KEY_B64: ${{ secrets.APPLE_KEY_B64 }} + APPLE_CERT_B64: ${{ secrets.APPLE_CERT_B64 }} + APPLE_CERT_PASSWORD: ${{ secrets.APPLE_CERT_PASSWORD }} + APPLE_KEYCHAIN_PASSWORD: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }} + run: | + # extract apple cert + APPLE_CERT_PATH=$RUNNER_TEMP/apple_cert.p12 + KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db + echo -n "$APPLE_CERT_B64" | base64 --decode --output $APPLE_CERT_PATH + + # extract apple key + mkdir -p ~/private_keys + APPLE_API_KEY_PATH=~/private_keys/AuthKey_$APPLE_API_KEY.p8 + echo -n "$APPLE_KEY_B64" | base64 --decode --output $APPLE_API_KEY_PATH + + # create temp keychain + security create-keychain -p "$APPLE_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security default-keychain -s $KEYCHAIN_PATH + security set-keychain-settings -lut 21600 $KEYCHAIN_PATH + security unlock-keychain -p "$APPLE_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + + # import keychain + security import $APPLE_CERT_PATH -P $APPLE_CERT_PASSWORD -A -t cert -f pkcs12 -k $KEYCHAIN_PATH + security find-identity -v $KEYCHAIN_PATH -p codesigning + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $APPLE_KEYCHAIN_PASSWORD $KEYCHAIN_PATH + + # generate + go generate ./... + + # resync system clock https://github.com/actions/runner/issues/2996#issuecomment-1833103110 + sudo sntp -sS time.windows.com + - name: Build ${{ matrix.go-arch }} + env: + APPLE_CERT_ID: ${{ secrets.APPLE_CERT_ID }} + APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }} + APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }} + APPLE_KEY_B64: ${{ secrets.APPLE_KEY_B64 }} + APPLE_CERT_B64: ${{ secrets.APPLE_CERT_B64 }} + APPLE_CERT_PASSWORD: ${{ secrets.APPLE_CERT_PASSWORD }} + APPLE_KEYCHAIN_PASSWORD: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }} + CGO_ENABLED: 1 + GOOS: darwin + GOARCH: ${{ matrix.go-arch }} + run: | + ZIP_OUTPUT=release/explored_${GOOS}_${GOARCH}.zip + mkdir -p release + go build -tags='netgo' -trimpath -o bin/ -a -ldflags '-s -w' ./cmd/explored + cp README.md LICENSE bin/ + /usr/bin/codesign --deep -f -v --timestamp -o runtime,library -s $APPLE_CERT_ID bin/explored + ditto -ck bin $ZIP_OUTPUT + xcrun notarytool submit -k ~/private_keys/AuthKey_$APPLE_API_KEY.p8 -d $APPLE_API_KEY -i $APPLE_API_ISSUER --wait --timeout 10m $ZIP_OUTPUT + - uses: actions/upload-artifact@v4 + with: + name: explored_darwin_${{ matrix.go-arch }} + path: release/* + build-windows: + runs-on: windows-latest + needs: [ test ] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: '1.21' + - name: Setup + shell: bash + run: | + dotnet tool install --global AzureSignTool + go generate ./... + - name: Build amd64 + env: + CGO_ENABLED: 1 + GOOS: windows + GOARCH: amd64 + shell: bash + run: | + mkdir -p release + ZIP_OUTPUT=release/explored_${GOOS}_${GOARCH}.zip + go build -tags='netgo' -trimpath -o bin/ -a -ldflags '-s -w -linkmode external -extldflags "-static"' ./cmd/explored + azuresigntool sign -kvu "${{ secrets.AZURE_KEY_VAULT_URI }}" -kvi "${{ secrets.AZURE_CLIENT_ID }}" -kvt "${{ secrets.AZURE_TENANT_ID }}" -kvs "${{ secrets.AZURE_CLIENT_SECRET }}" -kvc ${{ secrets.AZURE_CERT_NAME }} -tr http://timestamp.digicert.com -v bin/explored.exe + cp README.md LICENSE bin/ + 7z a $ZIP_OUTPUT ./bin/* + - uses: actions/upload-artifact@v4 + with: + name: explored_windows_amd64 + path: release/* + combine-release-assets: + runs-on: ubuntu-latest + needs: [ build-linux, build-mac, build-windows ] + steps: + - name: Merge Artifacts + uses: actions/upload-artifact/merge@v4 + with: + name: explored + +# dispatch-homebrew: # only runs on full releases +# if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-') +# needs: [ build-mac ] +# runs-on: ubuntu-latest +# steps: +# - name: Extract Tag Name +# id: get_tag +# run: echo "::set-output name=tag_name::${GITHUB_REF#refs/tags/}" +# +# - name: Dispatch +# uses: peter-evans/repository-dispatch@v3 +# with: +# token: ${{ secrets.PAT_REPOSITORY_DISPATCH }} +# repository: siafoundation/homebrew-sia +# event-type: release-tagged +# client-payload: > +# { +# "description": "explored: The Next-Gen Sia Explorer", +# "tag": "${{ steps.get_tag.outputs.tag_name }}", +# "project": "explored", +# "workflow_id": "${{ github.run_id }}" +# } +# dispatch-linux: # always runs +# needs: [ build-linux ] +# runs-on: ubuntu-latest +# steps: +# - name: Build Dispatch Payload +# id: get_payload +# uses: actions/github-script@v7 +# with: +# script: | +# const isRelease = context.ref.startsWith('refs/tags/v'), +# isBeta = isRelease && context.ref.includes('-beta'), +# tag = isRelease ? context.ref.replace('refs/tags/', '') : 'master'; +# +# let component = 'nightly'; +# if (isBeta) { +# component = 'beta'; +# } else if (isRelease) { +# component = 'main'; +# } +# +# return { +# description: "explored: The Next-Gen Sia Explorer", +# tag: tag, +# project: "explored", +# workflow_id: context.runId, +# component: component +# }; +# +# - name: Dispatch +# uses: peter-evans/repository-dispatch@v3 +# with: +# token: ${{ secrets.PAT_REPOSITORY_DISPATCH }} +# repository: siafoundation/linux +# event-type: release-tagged +# client-payload: ${{ steps.get_payload.outputs.result }} \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml index 0d11f13f..050db115 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -17,28 +17,8 @@ run: # list of build tags, all linters use it. Default is empty list. build-tags: [] - # which dirs to skip: issues from them won't be reported; - # can use regexp here: generated.*, regexp is applied on full path; - # default value is empty list, but default dirs are skipped independently - # from this option's value (see skip-dirs-use-default). - skip-dirs: - - cover - - # default is true. Enables skipping of directories: - # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ - skip-dirs-use-default: true - - # which files to skip: they will be analyzed, but issues from them - # won't be reported. Default value is empty list, but there is - # no need to include all autogenerated files, we confidently recognize - # autogenerated files. If it's not please let us know. - skip-files: [] - # output configuration options output: - # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" - format: colored-line-number - # print lines of code with issue, default is true print-issued-lines: true @@ -50,7 +30,6 @@ linters-settings: ## Enabled linters: govet: # report about shadowed variables - check-shadowing: false disable-all: false tagliatelle: @@ -65,23 +44,31 @@ linters-settings: # See https://go-critic.github.io/overview#checks-overview # To check which checks are enabled run `GL_DEBUG=gocritic golangci-lint run` # By default list of stable checks is used. - enabled-checks: - - argOrder # Diagnostic options - - badCond - - caseOrder - - dupArg - - dupBranchBody - - dupCase - - dupSubExpr - - nilValReturn - - offBy1 - - weakCond - - boolExprSimplify # Style options here and below. - - builtinShadow - - emptyFallthrough - - hexLiteral - - underef - - equalFold + enabled-tags: + - diagnostic + - style + disabled-checks: + # diagnostic + - appendAssign + - commentedOutCode + - uncheckedInlineErr + # style + - httpNoBody + - exitAfterDefer + - ifElseChain + - importShadow + - initClause + - nestingReduce + - octalLiteral + - paramTypeCombine + - ptrToRefParam + - stringsCompare + - tooManyResultsChecker + - typeDefFirst + - typeUnparen + - unlabelStmt + - unnamedResult + - whyNoLint revive: ignore-generated-header: true rules: @@ -90,7 +77,7 @@ linters-settings: - name: bool-literal-in-expr disabled: false - name: confusing-naming - disabled: true + disabled: false - name: confusing-results disabled: false - name: constant-logical-expr @@ -108,7 +95,7 @@ linters-settings: - name: increment-decrement disabled: false - name: modifies-value-receiver - disabled: false + disabled: true - name: optimize-operands-order disabled: false - name: range-val-in-closure @@ -154,12 +141,10 @@ issues: # But independently from this option we use default exclude patterns, # it can be disabled by `exclude-use-default: false`. To list all # excluded by default patterns execute `golangci-lint run --help` - exclude: - - "ifElseChain:.*" - - "exitAfterDefer:.*" + exclude: [] # Independently from option `exclude` we use default exclude patterns, # it can be disabled by this option. To list all # excluded by default patterns execute `golangci-lint run --help`. # Default value for this option is true. - exclude-use-default: false + exclude-use-default: false \ No newline at end of file diff --git a/cmd/explored/node.go b/cmd/explored/node.go index 190f06a7..06400432 100644 --- a/cmd/explored/node.go +++ b/cmd/explored/node.go @@ -155,7 +155,7 @@ func newNode(addr, dir string, chainNetwork string, useUPNP bool, logger *zap.Lo } cm := chain.NewManager(dbstore, tipState) - store, err := sqlite.OpenDatabase(filepath.Join(dir, "./explore.db"), logger) + store, err := sqlite.OpenDatabase(filepath.Join(dir, "explored.sqlite3"), logger) if err != nil { return nil, err } diff --git a/internal/syncerutil/store.go b/internal/syncerutil/store.go index 22a37f62..cbaecf05 100644 --- a/internal/syncerutil/store.go +++ b/internal/syncerutil/store.go @@ -23,7 +23,7 @@ type EphemeralPeerStore struct { mu sync.Mutex } -func (eps *EphemeralPeerStore) banned(peer string) bool { +func (eps *EphemeralPeerStore) isBanned(peer string) bool { host, _, err := net.SplitHostPort(peer) if err != nil { return false // shouldn't happen @@ -62,7 +62,7 @@ func (eps *EphemeralPeerStore) Peers() ([]syncer.PeerInfo, error) { defer eps.mu.Unlock() var peers []syncer.PeerInfo for addr, p := range eps.peers { - if !eps.banned(addr) { + if !eps.isBanned(addr) { peers = append(peers, p) } } @@ -109,7 +109,7 @@ func (eps *EphemeralPeerStore) Ban(peer string, duration time.Duration, reason s func (eps *EphemeralPeerStore) Banned(peer string) (bool, error) { eps.mu.Lock() defer eps.mu.Unlock() - return eps.banned(peer), nil + return eps.isBanned(peer), nil } // NewEphemeralPeerStore initializes an EphemeralPeerStore. @@ -205,5 +205,8 @@ func NewJSONPeerStore(path string) (*JSONPeerStore, error) { EphemeralPeerStore: NewEphemeralPeerStore(), path: path, } - return jps, jps.load() + if err := jps.load(); err != nil { + return nil, err + } + return jps, nil } diff --git a/persist/sqlite/store.go b/persist/sqlite/store.go index 7c03a7c2..1f79e421 100644 --- a/persist/sqlite/store.go +++ b/persist/sqlite/store.go @@ -88,9 +88,9 @@ func doTransaction(db *sql.DB, log *zap.Logger, fn func(tx *txn) error) error { Tx: tx, log: log, } - if err = fn(ltx); err != nil { + if err := fn(ltx); err != nil { return err - } else if err = tx.Commit(); err != nil { + } else if err := tx.Commit(); err != nil { return fmt.Errorf("failed to commit transaction: %w", err) } return nil