From 2b15499136b01ef4564ab4a1b9d06c8dd17396bb Mon Sep 17 00:00:00 2001 From: Yannis Tsopokis Date: Thu, 16 Jul 2026 17:06:41 +0300 Subject: [PATCH] Add linters and enhance pipelines --- .github/workflows/build.yml | 58 +++++++++++++++++++++++++++- .github/workflows/release.yml | 72 +++++++++++++++++++++++++++++++++++ .github/workflows/test.yml | 31 --------------- .golangci.yml | 12 ++++++ .markdownlint.yaml | 3 ++ .yamllint.yaml | 7 ++++ corteca-cli.Dockerfile | 25 ++++++++++++ scripts/check.sh | 65 +++++++++++++++++++++++++++++++ 8 files changed, 240 insertions(+), 33 deletions(-) create mode 100644 .github/workflows/release.yml delete mode 100644 .github/workflows/test.yml create mode 100644 .golangci.yml create mode 100644 .markdownlint.yaml create mode 100644 .yamllint.yaml create mode 100644 corteca-cli.Dockerfile create mode 100755 scripts/check.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 600c3cd..519b92c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,14 +11,68 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 # required for git describe --tags used in VERSION - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version-file: go.mod - name: Build run: make + + test: + name: Tests + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v5 + with: + fetch-depth: 0 # required for git describe --tags used in VERSION + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Run tests + run: make test + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v5 + with: + files: ./coverage.out + flags: unittests + token: ${{ secrets.CODECOV_TOKEN }} + + lint: + name: Lint + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v5 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Go lint + uses: golangci/golangci-lint-action@v7 + with: + version: latest + + - name: YAML lint + run: | + pip install --quiet yamllint + yamllint -c .yamllint.yaml . + + - name: Markdown lint + uses: DavidAnson/markdownlint-cli2-action@v18 + with: + config: .markdownlint.yaml + globs: '**/*.md' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..6b9145f --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,72 @@ +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + release: + name: Build and publish + runs-on: ubuntu-latest + permissions: + contents: write # create GitHub Release and upload assets + packages: write # push to GHCR + + steps: + - name: Checkout code + uses: actions/checkout@v5 + with: + fetch-depth: 0 # required for git describe --tags + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Install nfpm + run: go install github.com/goreleaser/nfpm/v2/cmd/nfpm@v2.40.0 + + - name: Get version + id: version + run: echo "version=$(git describe --tags)" >> "$GITHUB_OUTPUT" + + - name: Build packages + run: | + make deb DESTARCH=amd64 + make deb DESTARCH=arm64 + make rpm DESTARCH=amd64 + make rpm DESTARCH=arm64 + make osx DESTARCH=amd64 + make osx DESTARCH=arm64 + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + files: dist/packages/* + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push container image + uses: docker/build-push-action@v6 + with: + context: . + file: corteca-cli.Dockerfile + platforms: linux/amd64,linux/arm64 + push: true + build-args: | + VERSION=${{ steps.version.outputs.version }} + tags: | + ghcr.io/${{ github.repository }}:latest + ghcr.io/${{ github.repository }}:${{ steps.version.outputs.version }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 3d35284..0000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Tests - -on: - push: - pull_request: - -jobs: - test: - name: Tests - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 # required for git describe --tags used in VERSION - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version-file: go.mod - - - name: Run tests - run: make test - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5 - with: - files: ./coverage.out - flags: unittests - token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..1e98b6d --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,12 @@ +version: "2" + +run: + timeout: 5m + +linters: + enable: + - errcheck + - govet + - ineffassign + - staticcheck + - unused diff --git a/.markdownlint.yaml b/.markdownlint.yaml new file mode 100644 index 0000000..553fde5 --- /dev/null +++ b/.markdownlint.yaml @@ -0,0 +1,3 @@ +default: true +MD013: false # line length — not enforced +MD033: false # inline HTML — used in README (logo div) diff --git a/.yamllint.yaml b/.yamllint.yaml new file mode 100644 index 0000000..794a3dc --- /dev/null +++ b/.yamllint.yaml @@ -0,0 +1,7 @@ +extends: default + +rules: + line-length: + max: 120 + truthy: + allowed-values: ['true', 'false'] diff --git a/corteca-cli.Dockerfile b/corteca-cli.Dockerfile new file mode 100644 index 0000000..5853f33 --- /dev/null +++ b/corteca-cli.Dockerfile @@ -0,0 +1,25 @@ +# syntax=docker/dockerfile:1 +# +# Runtime container image for corteca CLI. +# Includes the corteca binary and Docker CLI (required for `docker buildx build`). +# +# Requires pre-built binaries in dist/bin/ (produced by `make`). +# See doc/BUILD.md for local build and test instructions. + +ARG DOCKER_VERSION=27 + +FROM docker:${DOCKER_VERSION}-cli + +LABEL org.opencontainers.image.title="corteca-cli" \ + org.opencontainers.image.description="Corteca Developer Toolkit — CLI for building and deploying Corteca applications" \ + org.opencontainers.image.source="https://github.com/nokia/corteca-cli" \ + org.opencontainers.image.licenses="BSD-3-Clause" + +RUN apk add --no-cache ca-certificates + +ARG TARGETARCH +ARG VERSION +COPY dist/bin/corteca-linux-${TARGETARCH}-${VERSION} /usr/local/bin/corteca +COPY data/ /etc/corteca/ + +ENTRYPOINT ["corteca"] diff --git a/scripts/check.sh b/scripts/check.sh new file mode 100755 index 0000000..b86cbe8 --- /dev/null +++ b/scripts/check.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +# Run the same checks as build.yml locally. +set -euo pipefail + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +BOLD='\033[1m' +RESET='\033[0m' + +pass() { echo -e "${GREEN}✓ $1${RESET}"; } +fail() { echo -e "${RED}✗ $1${RESET}"; exit 1; } +warn() { echo -e "${YELLOW}⚠ $1${RESET}"; } +header() { echo -e "\n${BOLD}=== $1 ===${RESET}"; } + +# ── Devcontainer guard ─────────────────────────────────────────────────────── +# Re-run inside the devcontainer if we're not already in one. +if [ -z "${IN_DEVCONTAINER:-}" ] && [ -z "${REMOTE_CONTAINERS:-}" ] && [ -z "${CODESPACES:-}" ]; then + header "Not inside devcontainer — spinning it up" + if ! command -v devcontainer &>/dev/null; then + fail "devcontainer CLI not found.\n Install: npm install -g @devcontainers/cli\n Or open this repo in VS Code and use 'Reopen in Container'." + fi + WORKSPACE="$(cd "$(dirname "$0")/.." && pwd)" + devcontainer up --workspace-folder "$WORKSPACE" || fail "devcontainer up failed" + exec devcontainer exec --workspace-folder "$WORKSPACE" bash scripts/check.sh +fi + +# ── Build ──────────────────────────────────────────────────────────────────── +header "Build" +make || fail "build failed" +pass "build" + +# ── Tests ──────────────────────────────────────────────────────────────────── +header "Tests" +make test || fail "tests failed" +pass "tests" + +# ── Go lint ────────────────────────────────────────────────────────────────── +header "Go lint (golangci-lint)" +if ! command -v golangci-lint &>/dev/null; then + fail "golangci-lint not found — install it or open the devcontainer" +fi +golangci-lint run ./... || fail "Go lint failed" +pass "Go lint" + +# ── YAML lint ──────────────────────────────────────────────────────────────── +header "YAML lint (yamllint)" +if ! command -v yamllint &>/dev/null; then + echo "yamllint not found, installing via apt..." + sudo apt-get install -y -qq yamllint +fi +yamllint -c .yamllint.yaml . || fail "YAML lint failed" +pass "YAML lint" + +# ── Markdown lint ──────────────────────────────────────────────────────────── +header "Markdown lint (markdownlint-cli2)" +if ! command -v npx &>/dev/null; then + warn "npx / Node.js not found — skipping markdown lint (runs in CI via GitHub Actions)" +else + npx --yes markdownlint-cli2 --config .markdownlint.yaml "**/*.md" || fail "Markdown lint failed" + pass "Markdown lint" +fi + +# ───────────────────────────────────────────────────────────────────────────── +echo -e "\n${GREEN}${BOLD}All available checks passed.${RESET}"