Skip to content
Closed
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
79 changes: 79 additions & 0 deletions .github/workflows/chronicle-image-pin-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,21 @@ name: chronicle-image-pin-gate
# the malformed @sha256- (hyphen, the cosign sig-tag form), and short/over-long/invalid
# digests. An embedded self-test asserts this on every run, so the detector cannot silently
# regress.
#
# Auto-pin: for same-repo PRs the gate resolves each changed chart's .image (the standard
# chronicle chart shape: image.repository + image.tag) to its multi-arch index digest, writes
# the pin into values.yaml, and pushes ONE commit to the PR branch with the Chronicle bot App
# token (which re-triggers the gate -> green). The render-flag below stays the verdict, so any
# non-standard or unresolvable image is still flagged for a manual pin. Fork PRs get no token
# (secrets are withheld), so they keep the flag-only behaviour.

on:
pull_request:
paths:
- 'charts/**'

# contents:read for the default token; the auto-pin push authenticates with the bot App token
# (contents:write), not GITHUB_TOKEN.
permissions:
contents: read

Expand All @@ -24,10 +33,38 @@ jobs:
name: chronicle image pin gate
runs-on: ubuntu-latest
steps:
# Mint the bot App token FIRST (same-repo PRs only) so the checkout persists it as the git
# credential and the auto-pin push is write-capable (push via origin, no extraheader clash).
# continue-on-error so a transient mint failure can't block the required gate.
- name: Mint Chronicle bot token (same-repo PRs)
id: bot-token
if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
continue-on-error: true
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
client-id: ${{ secrets.CHRONICLE_GITHUB_BOT_CLIENT_ID }}
private-key: ${{ secrets.CHRONICLE_GITHUB_BOT_PRIVATE_KEY }}
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
fetch-depth: 0
# PR HEAD branch so an auto-pin commit pushes cleanly; persisted credential is the bot
# App token for same-repo PRs (write), else the default GITHUB_TOKEN (read).
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
token: ${{ steps.bot-token.outputs.token || github.token }}
- uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4
# Best effort: public chronicle images resolve anonymously; private ones need this token.
# A login failure is fine -- the unresolved image just stays flagged by the render gate.
- name: Log in to GHCR for private image digests
continue-on-error: true
env:
GHCR_TOKEN: ${{ secrets.CHRONICLE_IMAGE_PULL_TOKEN }}
run: |
if [ -n "$GHCR_TOKEN" ]; then
echo "$GHCR_TOKEN" | docker login ghcr.io -u "${{ github.repository_owner }}" --password-stdin
else
echo "no CHRONICLE_IMAGE_PULL_TOKEN; resolving public images only"
fi
- name: Self-test detector, then gate changed charts
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
Expand Down Expand Up @@ -91,3 +128,45 @@ jobs:
done <<< "$changed"
if [ "$fail" -eq 0 ]; then echo "OK: all changed charts pin their chronicle default images."; fi
exit "$fail"
# Auto-pin the standard chronicle chart shape (image.repository + image.tag) for same-repo
# PRs and push ONE commit. Skipped without a bot token (fork / mint failure). The render
# gate above remains the verdict, so an unresolved or non-standard image stays flagged.
- name: Auto-pin chronicle image digests (one commit to the PR branch)
if: ${{ always() && github.event.pull_request.head.repo.full_name == github.repository && steps.bot-token.outputs.token != '' }}
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_REF: ${{ github.event.pull_request.head.ref }}
run: |
set -uo pipefail
if ! changed=$(git diff --name-only "${BASE_SHA}...HEAD" -- 'charts/*/values.yaml'); then
echo "::warning::auto-pin: could not compute the PR diff; skipping (the render gate still gates)."; exit 0
fi
[ -n "$changed" ] || { echo "No changed chart values.yaml."; exit 0; }
# Loop guard: never re-pin on top of an auto-pin (avoids a push -> re-run -> push cycle).
if git log -1 --pretty=%s | grep -q '^ci: auto-pin chronicle image digests'; then
echo "::warning::HEAD is already an auto-pin commit; skipping (loop guard)."; exit 0
fi
pinned_files=""
while IFS= read -r f; do
[ -f "$f" ] || continue
repo=$(yq -r '.image.repository // ""' "$f")
tag=$(yq -r '.image.tag // ""' "$f")
case "$repo" in ghcr.io/chronicleprotocol/*) ;; *) continue ;; esac
case "$tag" in ""|*@sha256:*) continue ;; esac
digest=$(docker buildx imagetools inspect "$repo:$tag" --format '{{.Manifest.Digest}}' 2>/dev/null || true)
case "$digest" in
sha256:*)
NEWTAG="$tag@$digest" yq -i '.image.tag = strenv(NEWTAG)' "$f"
pinned_files="$pinned_files $f"
echo "auto-pinned $f: $repo:$tag -> $tag@$digest"
;;
*) echo "::warning file=$f::could not resolve $repo:$tag to an index digest; left for the render gate" ;;
esac
done <<< "$changed"
[ -n "$pinned_files" ] || { echo "No auto-pins to push."; exit 0; }
git config user.name "chronicle-github-bot[bot]"
git config user.email "chronicle-github-bot[bot]@users.noreply.github.com"
git add -- $pinned_files
git commit -m "ci: auto-pin chronicle image digests"
git push origin "HEAD:${HEAD_REF}"
echo "::notice::pushed an auto-pin commit to ${HEAD_REF}; the re-run verifies it."
132 changes: 50 additions & 82 deletions charts/spire/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,17 @@
# Declare variables to be passed into your templates.

replicaCount: 1

image:
repository: ghcr.io/chronicleprotocol/spire
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: "0.68.3@sha256:79df4fb203224fa201623ae4d4f158faccfd410ec60f92841d161bb5b081d7ac"

imagePullSecrets: []
nameOverride: ""
fullnameOverride: "spire"

entryPointOverride: []
argsOverride: []
extraArgs: []

serviceAccount:
# Specifies whether a service account should be created
create: true
Expand All @@ -26,21 +22,17 @@ serviceAccount:
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""

podAnnotations: {}
podSecurityContext: {}
# fsGroup: 2000

podSecurityContext:
{}
# fsGroup: 2000

securityContext:
{}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000

service:
type: ClusterIP
Expand All @@ -54,25 +46,22 @@ service:
libp2p:
port: 8000
protocol: TCP
### to add more listeners for webapi, add them here
# rpc:
# port: 9100
# protocol: TCP
# webapi:
# port: 8080
# protocol: TCP
annotations:
{}
# external-dns.alpha.kubernetes.io/hostname: DOMAIN_NAME

### to add more listeners for webapi, add them here
# rpc:
# port: 9100
# protocol: TCP
# webapi:
# port: 8080
# protocol: TCP
annotations: {}
# external-dns.alpha.kubernetes.io/hostname: DOMAIN_NAME
# -- Optional ClusterIP metrics service for scraping metrics without exposing the metrics port on a public LoadBalancer.
metricsService:
enabled: false
annotations: {}
port: 9090
targetPort: 9090
protocol: TCP

# -- Liveness probe
liveness:
enabled: true
Expand All @@ -81,7 +70,6 @@ liveness:
port: libp2p
initialDelaySeconds: 10
periodSeconds: 10

# -- Readiness probe
readiness:
enabled: true
Expand All @@ -90,14 +78,12 @@ readiness:
port: libp2p
initialDelaySeconds: 10
periodSeconds: 10

ingress:
enabled: false
className: ""
annotations:
{}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: chart-example.local
paths:
Expand All @@ -107,77 +93,62 @@ ingress:
# - secretName: chart-example-tls
# hosts:
# - chart-example.local

resources:
{}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi

autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 100
targetCPUUtilizationPercentage: 80
targetMemoryUtilizationPercentage: 80

nodeSelector: {}

tolerations: []

affinity: {}

# Configurations for spire : default mode is to run as agent
# if true, runs bootstrap mode
bootstrap: false

# if true, runs stream mode
stream: true

# if true, runs as a watch mode
watch: false

# if true, runs spire in kafka made
kafka:
enabled: false
kafkaEnpoint: kafka.default.svc.cluster.local:9092
kafkaTopics: {}
# - "--topic"
# - "data-point-v1"
# - "data_point/v1"

# - "--topic"
# - "data-point-v1"
# - "data_point/v1"
# custom Args that may be added to the agent
customArgs: []

## logLevel is the log level for the spire server (debug,info,trace,etc)
logLevel: null

## logFormat is the log format for the spire server (json, or text)
logFormat: null

# Environment variable listing
env:
# non sensitive variables
# refer to https://github.com/chronicleprotocol/oracle-suite/tree/main/cmd/spire#environment-variables
normal: {}
# CFG_ITEM_SEPARATOR: "\n"
# CFG_FEEDS: stage
# CFG_LIBP2P_PK_SEED: "1234567981234567981234567981234567981234123456798123456798123456" # 64 bytes libp2p for bootstrap only
# CFG_LIBP2P_BOOTSTRAP_ADDRS: |-
# /dns/bootstrap.some.domain/tcp/8000/p2p/<some_libp2p_pub_key>

# CFG_ITEM_SEPARATOR: "\n"
# CFG_FEEDS: stage
# CFG_LIBP2P_PK_SEED: "1234567981234567981234567981234567981234123456798123456798123456" # 64 bytes libp2p for bootstrap only
# CFG_LIBP2P_BOOTSTRAP_ADDRS: |-
# /dns/bootstrap.some.domain/tcp/8000/p2p/<some_libp2p_pub_key>
# This is a config file for spire. it can override the default config if supplied
# It is in HCL format.
# For more information on HCL, see https://github.com/chronicleprotocol/oracle-suite/blob/main/config.hcl
configHcl: {}

serviceMonitor:
# -- If true, a ServiceMonitor CRD is created for a prometheus operator
# https://github.com/coreos/prometheus-operator
Expand All @@ -202,17 +173,14 @@ serviceMonitor:
scrapeTimeout: 30s
# -- ServiceMonitor relabelings
relabelings: []


# -- Extra K8s manifests to deploy
extraObjects:
[]
# - apiVersion: "kubernetes-client.io/v1"
# kind: ExternalSecret
# metadata:
# name: promtail-secrets
# spec:
# backendType: gcpSecretsManager
# data:
# - key: promtail-oauth2-creds
# name: client_secret
extraObjects: []
# - apiVersion: "kubernetes-client.io/v1"
# kind: ExternalSecret
# metadata:
# name: promtail-secrets
# spec:
# backendType: gcpSecretsManager
# data:
# - key: promtail-oauth2-creds
# name: client_secret
Loading