Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Docker & Helm

permissions: {}

on:
push:
tags: ["v*"]
branches: [main]
pull_request:

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
lint-chart:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
permissions:
contents: read
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4
- uses: helm/chart-testing-action@0d28d3144d3a25ea2cc349d6e59901c4ff469b3b # v2.7.0
- run: ct lint --target-branch "$BASE_REF" --charts charts/version-guard
env:
BASE_REF: ${{ github.event.pull_request.base.ref }}

build-and-push:
runs-on: ubuntu-latest
if: github.repository == 'block/Version-Guard'
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Set up QEMU
if: github.event_name != 'pull_request'
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3

- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3

- name: Login to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5
id: meta
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=
type=semver,pattern=v{{version}}
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and push
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
with:
context: .
file: deploy/Dockerfile
platforms: ${{ github.event_name != 'pull_request' && 'linux/amd64,linux/arm64' || 'linux/amd64' }}
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: VERSION=${{ github.ref_name }}

- name: Package and push Helm chart
if: startsWith(github.ref, 'refs/tags/v')
run: |
TAG_VERSION="${GITHUB_REF_NAME#v}"
CHART_VERSION=$(yq '.version' charts/version-guard/Chart.yaml)
if [ "$TAG_VERSION" != "$CHART_VERSION" ]; then
echo "::error::Tag ${GITHUB_REF_NAME} does not match Chart.yaml version ${CHART_VERSION}"
exit 1
fi
helm package charts/version-guard --destination ./build
echo "$HELM_TOKEN" | helm registry login ghcr.io -u "$HELM_USER" --password-stdin
helm push ./build/version-guard-${CHART_VERSION}.tgz oci://ghcr.io/block/charts
env:
HELM_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HELM_USER: ${{ github.actor }}
3 changes: 2 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ jobs:
- name: Run linter
uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1
with:
version: v1.62.2
version: v1.64.8
only-new-issues: true

- name: Check formatting
run: |
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ run-server: build ## Run gRPC server locally
.PHONY: docker-build
docker-build: ## Build Docker image
@echo "🐳 Building Docker image..."
@docker build -t block/version-guard:latest .
@docker build -t block/version-guard:latest -f deploy/Dockerfile .
@echo "✅ Docker image built: block/version-guard:latest"

.PHONY: docker-run
Expand Down
3 changes: 3 additions & 0 deletions charts/version-guard/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.git
.gitignore
*.md
9 changes: 9 additions & 0 deletions charts/version-guard/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v2
name: version-guard
description: Cloud infrastructure version drift and EOL detection
type: application
version: 0.1.0
appVersion: "0.1.0"
maintainers:
- name: bakayolo
url: https://github.com/bakayolo
40 changes: 40 additions & 0 deletions charts/version-guard/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{{- define "version-guard.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{- define "version-guard.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}

{{- define "version-guard.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{- define "version-guard.labels" -}}
helm.sh/chart: {{ include "version-guard.chart" . }}
{{ include "version-guard.selectorLabels" . }}
app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{- define "version-guard.selectorLabels" -}}
app.kubernetes.io/name: {{ include "version-guard.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{- define "version-guard.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "version-guard.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
55 changes: 55 additions & 0 deletions charts/version-guard/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "version-guard.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "version-guard.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "version-guard.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "version-guard.selectorLabels" . | nindent 8 }}
spec:
serviceAccountName: {{ include "version-guard.serviceAccountName" . }}
securityContext:
runAsNonRoot: true
runAsUser: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: version-guard
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
ports:
- name: grpc
containerPort: {{ .Values.containerPort }}
protocol: TCP
env:
- name: GRPC_PORT
value: {{ .Values.containerPort | quote }}
{{- with .Values.env }}
{{- toYaml . | nindent 12 }}
{{- end }}
livenessProbe:
tcpSocket:
port: grpc
initialDelaySeconds: 10
periodSeconds: 15
readinessProbe:
tcpSocket:
port: grpc
initialDelaySeconds: 5
periodSeconds: 10
resources:
{{- toYaml .Values.resources | nindent 12 }}
16 changes: 16 additions & 0 deletions charts/version-guard/templates/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "version-guard.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "version-guard.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: grpc
protocol: TCP
name: grpc
selector:
{{- include "version-guard.selectorLabels" . | nindent 4 }}
13 changes: 13 additions & 0 deletions charts/version-guard/templates/serviceaccount.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "version-guard.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "version-guard.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
27 changes: 27 additions & 0 deletions charts/version-guard/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
replicaCount: 1

image:
repository: ghcr.io/block/version-guard
tag: ""
pullPolicy: IfNotPresent

serviceAccount:
create: true
name: ""
annotations: {}

containerPort: 8080

service:
type: ClusterIP
port: 8080

env: []

resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 1000m
memory: 512Mi
16 changes: 16 additions & 0 deletions deploy/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM golang:1.24.2-alpine AS builder
RUN apk add --no-cache git
WORKDIR /src
COPY go.mod go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod go mod download
COPY . .
ARG VERSION=dev
RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build \
CGO_ENABLED=0 go build -ldflags="-s -w -X main.version=${VERSION}" -o /version-guard ./cmd/server

FROM alpine:3.21
RUN apk add --no-cache ca-certificates tzdata && adduser -D -u 1000 version-guard
USER version-guard
COPY --from=builder /version-guard /app/version-guard
EXPOSE 8080
ENTRYPOINT ["/app/version-guard"]
6 changes: 3 additions & 3 deletions pkg/eol/aws/eks_endoflife_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,9 @@ func TestEKSEOLProvider_WithEndOfLifeClient(t *testing.T) {
return []*endoflife.ProductCycle{
{
Cycle: "1.35",
ReleaseDate: "2025-11-20", // Different from static
EOL: "2027-12-20", // End of standard support
ExtendedSupport: "2029-05-20", // End of extended support
ReleaseDate: "2025-11-20", // Different from static
EOL: "2027-12-20", // End of standard support
ExtendedSupport: "2029-05-20", // End of extended support
},
}, nil
},
Expand Down
14 changes: 7 additions & 7 deletions pkg/eol/endoflife/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ type Client interface {
// ProductCycle represents a single version/cycle from endoflife.date API
// API docs: https://endoflife.date/docs/api/
type ProductCycle struct {
Cycle string `json:"cycle"` // Version identifier (e.g., "1.31")
ReleaseDate string `json:"releaseDate"` // Release date (YYYY-MM-DD)
Support string `json:"support"` // End of standard support (YYYY-MM-DD or boolean)
EOL string `json:"eol"` // End of life date (YYYY-MM-DD or boolean)
ExtendedSupport any `json:"extendedSupport"` // Extended support availability (boolean or date)
LTS bool `json:"lts"` // Long-term support flag
Latest string `json:"latest"` // Latest patch version
Cycle string `json:"cycle"` // Version identifier (e.g., "1.31")
ReleaseDate string `json:"releaseDate"` // Release date (YYYY-MM-DD)
Support string `json:"support"` // End of standard support (YYYY-MM-DD or boolean)
EOL string `json:"eol"` // End of life date (YYYY-MM-DD or boolean)
ExtendedSupport any `json:"extendedSupport"` // Extended support availability (boolean or date)
LTS bool `json:"lts"` // Long-term support flag
Latest string `json:"latest"` // Latest patch version
LatestReleaseDate string `json:"latestReleaseDate"` // Latest patch release date
}

Expand Down
1 change: 1 addition & 0 deletions pkg/eol/endoflife/integration_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build integration
// +build integration

package endoflife
Expand Down
24 changes: 12 additions & 12 deletions pkg/eol/endoflife/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ import (

// ProductMapping maps internal engine names to endoflife.date product identifiers
var ProductMapping = map[string]string{
"kubernetes": "amazon-eks",
"k8s": "amazon-eks",
"eks": "amazon-eks",
"postgres": "amazon-rds-postgresql",
"postgresql": "amazon-rds-postgresql",
"mysql": "amazon-rds-mysql",
"aurora-mysql": "amazon-rds-mysql",
"aurora-postgresql": "amazon-rds-postgresql",
"redis": "amazon-elasticache-redis",
"elasticache-redis": "amazon-elasticache-redis",
"valkey": "valkey",
"elasticache-valkey": "valkey",
"kubernetes": "amazon-eks",
"k8s": "amazon-eks",
"eks": "amazon-eks",
"postgres": "amazon-rds-postgresql",
"postgresql": "amazon-rds-postgresql",
"mysql": "amazon-rds-mysql",
"aurora-mysql": "amazon-rds-mysql",
"aurora-postgresql": "amazon-rds-postgresql",
"redis": "amazon-elasticache-redis",
"elasticache-redis": "amazon-elasticache-redis",
"valkey": "valkey",
"elasticache-valkey": "valkey",
}

// Provider fetches EOL data from endoflife.date API
Expand Down
1 change: 0 additions & 1 deletion pkg/inventory/wiz/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,4 +222,3 @@ func parseTagObject(tagObj string) (key, value string) {

return key, value
}

Loading