diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c218f55 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,106 @@ +name: CI + +on: + pull_request: + branches: [master, develop] + push: + branches: [master, develop] + +permissions: + contents: read + +jobs: + checks: + name: Checks (${{ matrix.os }}) + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + + - name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 + with: + go-version: "1.25.x" + + - name: Setup Node + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: "24" + cache: pnpm + + - name: Install pnpm + run: npm install --global pnpm@10.33.0 + + - name: Install Node dependencies + run: pnpm install --frozen-lockfile + + - name: Check package versions + run: pnpm version:check + + - name: Run Node tests + run: pnpm test + + - name: Run Go tests without skips + run: pnpm test:go + + - name: Run Go vet + run: go vet ./... + + quality: + name: Format and vulnerability checks + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + + - name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 + with: + go-version: "1.25.x" + + - name: Check Go formatting + run: test -z "$(gofmt -l $(git ls-files '*.go'))" + + - name: Install govulncheck + run: go install golang.org/x/vuln/cmd/govulncheck@v1.7.0 + + - name: Run govulncheck + run: govulncheck ./... + + npm-smoke: + name: npm tarball smoke test + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + + - name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 + with: + go-version: "1.25.x" + + - name: Setup Node + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: "24" + + - name: Build binaries + run: bash scripts/build-all.sh v2.0.0-smoke + + - name: Prepare platform packages + run: bash scripts/prepare-npm-packages.sh build + + - name: Pack npm packages + run: | + mkdir -p dist/npm + npm pack --pack-destination dist/npm + for package_dir in npm/linux-x64 npm/linux-arm64 npm/darwin-x64 npm/darwin-arm64 npm/win32-x64; do + npm pack "./$package_dir" --pack-destination dist/npm + done + + - name: Smoke test npm tarballs + run: npm run test:npm-smoke diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f651cbc..c9c2fbe 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -9,81 +9,73 @@ permissions: contents: write id-token: write +concurrency: + group: publish-${{ github.ref }} + cancel-in-progress: false + jobs: - pipeline: - name: Build (${{ matrix.goos }}-${{ matrix.goarch }}) + publish: + name: Build and publish runs-on: ubuntu-latest - - strategy: - matrix: - include: - - goos: linux - goarch: amd64 - artifact: opencore-linux-amd64 - isPublisher: false - - - goos: darwin - goarch: amd64 - artifact: opencore-darwin-amd64 - isPublisher: false - - - goos: darwin - goarch: arm64 - artifact: opencore-darwin-arm64 - isPublisher: false - - - goos: windows - goarch: amd64 - artifact: opencore-windows-amd64.exe - isPublisher: true - steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + fetch-depth: 0 - name: Setup Go - uses: actions/setup-go@v5 + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 with: - go-version: "1.24.5" + go-version: "1.25.x" - - name: Go tests - if: ${{ matrix.isPublisher }} - run: go test ./... + - name: Setup Node + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: "24" + registry-url: "https://registry.npmjs.org" + cache: pnpm - - name: Build binary - env: - GOOS: ${{ matrix.goos }} - GOARCH: ${{ matrix.goarch }} - CGO_ENABLED: 0 + - name: Install pnpm + run: npm install --global pnpm@10.33.0 + + - name: Install Node dependencies + run: pnpm install --frozen-lockfile + + - name: Verify tag is on a release branch run: | - go build -ldflags "-X main.version=${{ github.ref_name }}" -o "${{ matrix.artifact }}" . + git fetch origin develop master + if git merge-base --is-ancestor "$GITHUB_SHA" origin/develop || git merge-base --is-ancestor "$GITHUB_SHA" origin/master; then + exit 0 + fi + echo "Tag commit $GITHUB_SHA is not contained in develop or master." + exit 1 - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.artifact }} - path: ${{ matrix.artifact }} + - name: Run release preflight + run: pnpm release:check -- "${{ github.ref_name }}" - - name: Setup Node - if: ${{ matrix.isPublisher }} - uses: actions/setup-node@v4 - with: - node-version: "24" + - name: Build binaries + run: bash scripts/build-all.sh "${{ github.ref_name }}" + + - name: Prepare platform packages + run: bash scripts/prepare-npm-packages.sh build - - name: Update package version - if: ${{ matrix.isPublisher }} - shell: bash + - name: Pack npm packages run: | - VERSION=${GITHUB_REF#refs/tags/v} - npm version "$VERSION" --no-git-tag-version --allow-same-version + mkdir -p dist/npm + npm pack --pack-destination dist/npm + for package_dir in npm/linux-x64 npm/linux-arm64 npm/darwin-x64 npm/darwin-arm64 npm/win32-x64; do + npm pack "./$package_dir" --pack-destination dist/npm + done + + - name: Smoke test npm tarballs + run: pnpm test:npm-smoke - name: Resolve release channel - if: ${{ matrix.isPublisher }} id: channel - shell: bash + env: + VERSION: ${{ github.ref_name }} run: | - VERSION=${GITHUB_REF#refs/tags/v} - if [[ "$VERSION" == *-* ]]; then + if [[ "${VERSION}" == *-* ]]; then echo "channel=beta" >> "$GITHUB_OUTPUT" echo "prerelease=true" >> "$GITHUB_OUTPUT" else @@ -91,34 +83,33 @@ jobs: echo "prerelease=false" >> "$GITHUB_OUTPUT" fi - - name: Publish to NPM (Trusted Publisher) - if: ${{ matrix.isPublisher }} + - name: Publish packages idempotently env: - NODE_AUTH_TOKEN: "" - NPM_TOKEN: "" - run: npm publish --access public --provenance --tag "${{ steps.channel.outputs.channel }}" - - - name: Download all artifacts - if: ${{ matrix.isPublisher }} - uses: actions/download-artifact@v4 - with: - path: ./artifacts - - - name: Prepare release assets - if: ${{ matrix.isPublisher }} - shell: bash + CHANNEL: ${{ steps.channel.outputs.channel }} + VERSION: ${{ github.ref_name }} run: | - mkdir -p release - find ./artifacts -type f -maxdepth 2 -exec cp {} ./release/ \; - ls -lah ./release/ + version=${VERSION#v} + publish_if_missing() { + package_dir=$1 + package_name=$(node -p "require('./${package_dir}/package.json').name") + if npm view "${package_name}@${version}" version >/dev/null 2>&1; then + echo "${package_name}@${version} is already published." + else + (cd "$package_dir" && npm publish --access public --provenance --tag "$CHANNEL") + fi + } + for package_dir in npm/linux-x64 npm/linux-arm64 npm/darwin-x64 npm/darwin-arm64 npm/win32-x64; do + publish_if_missing "$package_dir" + done + publish_if_missing . + + - name: Generate checksums + run: (cd build && sha256sum opencore-* > SHA256SUMS) - name: Create GitHub Release - if: ${{ matrix.isPublisher }} - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 with: - files: ./release/* + files: build/* draft: false prerelease: ${{ steps.channel.outputs.prerelease }} body_path: RELEASE.md - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 0678082..3f5bbce 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,8 @@ *.dll *.so *.dylib -opencore -opencore-* +/opencore +/opencore-* !scripts/*.sh # Test binary @@ -34,4 +34,3 @@ Thumbs.db # NPM node_modules/ npm/*.tgz -pnpm-lock.yaml \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml index 6d45665..30b776b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,22 +1,25 @@ +version: "2" + linters: enable: - errcheck - - gosimple - govet - ineffassign - staticcheck - unused + exclusions: + rules: + - path: _test\.go + linters: + - errcheck + +formatters: + enable: - gofmt - goimports - -linters-settings: - gofmt: - simplify: true - goimports: - local-prefixes: github.com/newcore-network/opencore-cli - -issues: - exclude-rules: - - path: _test\.go - linters: - - errcheck + settings: + gofmt: + simplify: true + goimports: + local-prefixes: + - github.com/newcore-network/opencore-cli diff --git a/Makefile b/Makefile index 70ca81c..c8a7f4d 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: build build-all clean install test +.PHONY: build build-all clean install test lint deps VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev") LDFLAGS := -ldflags "-X main.version=$(VERSION)" @@ -9,10 +9,12 @@ build: # Build for all platforms build-all: clean + mkdir -p build GOOS=windows GOARCH=amd64 go build $(LDFLAGS) -o build/opencore-windows-amd64.exe . GOOS=darwin GOARCH=amd64 go build $(LDFLAGS) -o build/opencore-darwin-amd64 . GOOS=darwin GOARCH=arm64 go build $(LDFLAGS) -o build/opencore-darwin-arm64 . GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o build/opencore-linux-amd64 . + GOOS=linux GOARCH=arm64 go build $(LDFLAGS) -o build/opencore-linux-arm64 . # Clean build artifacts clean: @@ -35,4 +37,3 @@ lint: deps: go mod download go mod tidy - diff --git a/README.md b/README.md index ad3d090..74066b1 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,23 @@ This may be outdated, the latest information is recommended at [opencorejs.dev]( npm install -g @open-core/cli ``` +The CLI can also be installed with pnpm or Yarn Classic: + +```bash +pnpm add -g @open-core/cli +yarn global add @open-core/cli +``` + +Run without installing globally: + +```bash +npx @open-core/cli +``` + +The npm package installs a prebuilt binary for the current platform. It does +not run installation scripts or download binaries after npm has installed the +packages. GitHub Releases remain available for manual downloads. + ### Go ```bash @@ -72,7 +89,7 @@ go build -o opencore . | `opencore clone