sparks-core (Example Spark Library)

sparks-core is an example of a spark library -- a reusable Go module that provides pipeline helpers. It is not part of the sparkwing SDK and is not required to use sparkwing. It demonstrates the pattern of extracting common pipeline logic into shared libraries: your own spark libraries can provide whatever your team needs.

Install: go get github.com/sparkwing-dev/sparks-core@latest

The exact, current API -- every function signature, type, and field -- is on pkg.go.dev: pkg.go.dev/github.com/sparkwing-dev/sparks-core. This page is a conceptual tour of what the library offers and how the pieces fit together; treat the godoc as authoritative for signatures.

Every helper that does work takes a context.Context as its first argument and returns an error (sparkwing reports the error as a step failure). They do not panic.

PackagesSection anchor link

A representative set -- see the godoc for the full list:

PackagePurpose
checksPre-commit/pre-push checks: formatting, vet, tests, trailing newlines
dockerDocker build, push, ECR login, and multi-registry detection
gitopsGitOps deploy: clone, patch image tags, push, ArgoCD sync
kubeKubernetes helpers: kubectl apply/rollout, kustomize, node-arch detection
awsAWS profile / IRSA detection for CLI invocations
deployDeploy orchestrator: routes to gitops+ArgoCD or local kubectl
rollbackRollback orchestrator (the inverse of deploy)
s3S3 static-site deployment with correct cache headers
notifyWebhook / Slack notifications
probeHTTP health probes for post-deploy verification
servicesEphemeral Docker services (e.g. Postgres) for tests
templatesPipeline template registry and rendering

checksSection anchor link

Pre-commit and pre-push validation. Each function checks one thing and returns an error describing what failed:

  • GoFmt -- all git-tracked .go files are formatted.
  • GoVet -- go vet on the given packages (default ./...).
  • GoTestShort / GoTest -- go test, with or without -short.
  • TrailingNewlines -- all git-tracked text files end with a newline.

GoVet, GoTestShort, and GoTest accept package patterns. For a polyglot monorepo, pass a subdirectory pattern like "./services/api/..."; if that subdirectory has its own go.mod, the command rewrites itself to run in that module.

import "github.com/sparkwing-dev/sparks-core/checks"

checks.GoFmt(ctx)
checks.GoVet(ctx)                    // ./...
checks.GoTestShort(ctx, "./api/...") // multi-module

dockerSection anchor link

Docker build, push, and ECR helpers.

BuildAndPush builds an image and pushes it to one or more registries, handling ECR login and repository creation automatically. Its Tags field takes a docker.ImageTag value from the SDK (sparkwing/docker, via docker.ComputeTags) -- see sdk-reference.md for how content-addressed tags are derived. sparks-core itself does not compute tags; it consumes the SDK's.

import "github.com/sparkwing-dev/sparks-core/docker"

docker.BuildAndPush(ctx, docker.BuildConfig{
    Image:      "myapp",
    Dockerfile: "Dockerfile",
    Context:    ".",
    Registries: registries,
    Tags:       tags,           // a sparkwing/docker.ImageTag
    Platform:   "linux/arm64",  // optional cross-compile target
})

DetectRegistries(cluster, defaultECR) and DetectLocalRegistries(cluster) return the available push targets (and an error). The local form skips ECR for local-only builds.

gitopsSection anchor link

Clone a gitops repo, patch image tags in kustomization.yaml, push, and optionally sync ArgoCD. Deploy retries on concurrent push conflicts and reports whether it changed anything.

Transport: the initial clone is via gitcache when reachable (a fast read cache); the push always goes direct to GitHub over HTTPS with a PAT (GITHUB_TOKEN), falling back to SSH. gitcache is never a push target.

Before pushing, Deploy calls the sparkwing controller's authorization endpoint for audit logging; set SPARKWING_NO_VERIFY=1 to skip it (break-glass).

import "github.com/sparkwing-dev/sparks-core/gitops"

gitops.Deploy(ctx, gitops.DeployConfig{
    GitopsRepo: "git@github.com:your-org/gitops.git",
    GitopsPath: "sparkwing",
    ECR:        "123456789012.dkr.ecr.us-west-2.amazonaws.com",
    Images:     []string{"myapp"},
    Tag:        tags.ProdTag(),
})
gitops.SyncArgoCD(ctx, "sparkwing")

kubeSection anchor link

Kubernetes deployment and cluster detection: IsRunningInK8s, DetectNodeArch (returns a Docker platform string like "linux/arm64", handy when building on ARM Macs for Graviton nodes), DeployKubectl (rollout restart), DeployKustomize / DeployKindKustomize (pin image tags and kubectl apply -k), plus lower-level Apply, SetImage, and RolloutUndo.

import "github.com/sparkwing-dev/sparks-core/kube"

kube.DeployKubectl(ctx,
    []string{"myapp"},
    map[string]string{"myapp": "deploy/myapp"},
    "default",
)

awsSection anchor link

ProfileFlag(defaultProfile) returns " --profile <name>" for local development, or "" under IRSA (EKS), so you can append it directly to an AWS CLI command. ProfileArgs is the slice form. IsIRSA reports whether a web-identity token is mounted. aws.DefaultProfile is "default".

import "github.com/sparkwing-dev/sparks-core/aws"

flag := aws.ProfileFlag("staging")
sparkwing.Bash(ctx, "aws s3 ls"+flag).Run()
// Local:  aws s3 ls --profile staging
// EKS:    aws s3 ls

deploySection anchor link

High-level orchestrator that picks a deploy strategy:

  • Prod (gitops): pushes image tags to the gitops repo via gitops.Deploy, then syncs ArgoCD.
  • Local (kind): restarts deployments directly via kubectl, or applies a repo-owned k8s/ kustomization when present.

The routing decision is based on cfg.Local and the SPARKWING_KIND_CLUSTER environment variable (which sparkwing sets when the resolved profile targets a kind cluster), not on whether the code happens to run inside a cluster. A laptop deploy to prod still goes through gitops.

import "github.com/sparkwing-dev/sparks-core/deploy"

deploy.Run(ctx, deploy.Config{
    GitopsRepo: "git@github.com:your-org/gitops.git",
    GitopsPath: "sparkwing",
    ECR:        "123456789012.dkr.ecr.us-west-2.amazonaws.com",
    Images:     []string{"myapp"},
    Tag:        tags.ProdTag(),
    AppName:    "sparkwing",
    Namespace:  "sparkwing",
    DeployMap:  imageDeployment,
})

s3Section anchor link

DeployStaticSite syncs a build directory to S3 with cache headers tuned for CDN serving: non-HTML assets (JS, CSS, images -- bundler-fingerprinted) get a one-year immutable cache; HTML files get no-cache so visitors always get fresh markup. It returns per-pass upload counts so callers can detect an inconsistent deploy (new chunks shipped while HTML is unchanged). AWSProfile is required.

import "github.com/sparkwing-dev/sparks-core/s3"

res, err := s3.DeployStaticSite(ctx, s3.StaticSiteConfig{
    Bucket:     "my-website-bucket",
    OutDir:     "out",
    AWSProfile: "prod",  // required
})

Environment variablesSection anchor link

sparks-core reads these (most are set automatically by sparkwing when it launches a runner):

VariableUsed byPurpose
SPARKWING_KIND_CLUSTERdeploy, rollback, docker, kubeRoutes deploys into local-kubectl mode
SPARKWING_KUBE_CONTEXTkubeKubectl context override
SPARKWING_KUBE_ALLOW_CURRENTkubeOpt in to the current kubeconfig context
SPARKWING_REGISTRYdockerLocal registry override
SPARKWING_ECR_REGISTRYdockerECR registry override
SPARKWING_CONTROLLERgitopsController URL for deploy authorization
SPARKWING_NO_VERIFYgitopsSkip deploy authorization (break-glass)
GITHUB_TOKENgitopsGitHub PAT for HTTPS push
AWS_PROFILEawsAWS profile name
AWS_WEB_IDENTITY_TOKEN_FILEawsIRSA detection
KUBERNETES_SERVICE_HOSTkubeIn-cluster detection