Skip to content

Commit

Permalink
feat: update chart of cdviz-collector to support multiple config files
Browse files Browse the repository at this point in the history
+ demo for github webhook
  • Loading branch information
davidB committed Jan 30, 2025
1 parent ce71872 commit 7b1ee20
Show file tree
Hide file tree
Showing 6 changed files with 284 additions and 22 deletions.
25 changes: 25 additions & 0 deletions charts/cdviz-collector/config_files/cdviz-collector.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[sinks.debug]
enabled = true

[sinks.cdviz_db]
enabled = false

[sources.cdevents_webhook]
enabled = false

[sources.cdevents_webhook.extractor]
type = "webhook"
id = "000"

[sources.github_webhook]
enabled = false

[sources.github_webhook.extractor]
type = "webhook"
id = "001"
headers_to_keep = []
signature = { signature_encoding = "hex", signature_on = "body", signature_prefix = "sha256=", header = "x-hub-signature-256", token = "changeme" }

[transformers.github_events]
type = "vrl"
template_file = "./cnv_github_events.vrl"
194 changes: 194 additions & 0 deletions charts/cdviz-collector/config_files/cnv_github_events.vrl
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# Convert [github events](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads)
# to [cdevents](https://cdevents.dev)
#
# | done | Gihub Event | cdevent |
# | --- | --- | --- |
# | [x] | package:published | artifact:published |
# | [ ] | package:updated | artifact:published |
# | [x] | release:published | artifact:published |
# | [ ] | release:published/assets | artifact:published |
# | [ ] | release:unpublished | artifact:deleted |
# | [ ] | release:unpublished/assets | artifact:deleted |
# | [x] | workflow_run:requested | pipelineRun:queued |
# | [x] | workflow_run:in_progress | pipelineRun:started |
# | [x] | workflow_run:completed | pipelineRun:finished |
# | [x] | workflow_job:in_progress | taskRun:started |
# | [x] | workflow_job:completed | taskRun:finished |
#

body = null
id = "0" # "0" to let collector generate an id (alternative reuse github event id: .headers["X-GitHub-Delivery"])
repo_full_name = .body.repository.full_name
sender = .body.sender.login
# test existance of a field to determine the event type (alternative: .headers["X-GitHub-Event"])
if exists(.body.package) {
if .body.action == "published" {
ts = parse_timestamp(.body.package.updated_at, "%+") ?? now()
ts = format_timestamp!(ts, format: "%+")
name = .body.package.name || "noname"
namespace = .body.package.namespace || "nonamespace"
# [purl-spec/PURL-TYPES.rst at master · package-url/purl-spec](https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst)
pkg = null
# the case of the value seems inconsitent
# see [List packages for an organization](https://docs.github.com/en/rest/packages/packages?apiVersion=2022-11-28#list-packages-for-an-organization)
# see https://github.com/octokit/webhooks.net/blob/main/src/Octokit.Webhooks/Models/PackageType.cs
package_type = downcase(.body.package.package_type) ?? .body.package.package_type
if package_type == "container" && .body.package.package_version.container_metadata.tag.name != "" {
# [Container registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry)
version = (.body.package.package_version.container_metadata.tag.digest || .body.package.package_version.version)
version = encode_percent(version) ?? ""
tag = encode_percent(.body.package.package_version.container_metadata.tag.name) ?? ""
pkg = "pkg:oci/{{ name }}@{{ version }}?repository_url=ghcr.io/{{ namespace }}&tag={{ tag }}" ?? ""
} else if package_type == "docker" && .body.package.package_version.docker_metadata.tags[0] != "" {
# [Docker registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-docker-registry)
version = .body.package.package_version.version
# version = encode_percent() ?? ""
tag = encode_percent(.body.package.package_version.docker_metadata.tags[0]) ?? ""
pkg = "pkg:oci/{{ name }}@{{ version }}?repository_url=ghcr.io/{{ namespace }}&tag={{ tag }}" ?? ""
} else if package_type == "maven" {
# [Apache Maven registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-apache-maven-registry)
# [Gradle registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-gradle-registry)
version = .body.package.package_version.version
# version = encode_percent(version) ?? ""
repository_url = encode_percent("https://maven.pkg.github.com/{{ repo_full_name}}" ?? "")
pkg = "pkg:maven/{{ namespace }}/{{ name }}@{{ version }}?repository_url={{ repository_url }}" ?? ""
} else if package_type == "npm" && .body.package.package_version.npm_metadata.tag.name != "" {
# [npm registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry)
version = (.body.package.package_version.npm_metadata.version || .body.package.package_version.npm_metadata.npm_version || .body.package.package_version.version)
# version = encode_percent(version) ?? ""
repository_url = encode_percent("https://npm.pkg.github.com")
pkg = "pkg:npm/{{ namespace }}/{{ name }}@{{ version }}?repository_url={{ repository_url }}" ?? ""
} else if package_type == "nuget" {
# [NuGet registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-nuget-registry)
version = .body.package.package_version.version
# version = encode_percent(version) ?? ""
repository_url = encode_percent("https://nuget.pkg.github.com/{{ namespace }}" ?? "")
pkg = "pkg:nuget/{{ name }}@{{ version }}?repository_url={{ repository_url }}" ?? ""
} else if package_type == "rubygems" {
# [RubyGems registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-rubygems-registry)
version = (.body.package.package_version.rugygems_metadata.version_info.version || .body.package.package_version.version)
# version = encode_percent(version) ?? ""
repository_url = encode_percent("https://rubygems.pkg.github.com/{{ namespace }}" ?? "")
pkg = "pkg:gem/{{ name }}@{{ version }}?repository_url={{ repository_url }}" ?? ""
}

if pkg != null {
body = {
"context": {
"version": "0.4.1",
"id": id,
"source": "/api.github.com/repos/{{ repo_full_name }}/packages" ?? "",
"type": "dev.cdevents.artifact.published.0.2.0",
"timestamp": ts,
# "chainId": ??
# "links": ??
},
"subject": {
"id": pkg,
"source": .body.package.package_version.package_url,
"type": "artifact",
"user": sender,
}
}
}
}
} else if exists(.body.release) {
if .body.action == "published" {
ts = parse_timestamp(.body.release.published_at, "%+") ?? now()
ts = format_timestamp!(ts, format: "%+")
version = .body.release.tag_name
# version = encode_percent(version) ?? ""
pkg = "pkg:github/{{ repo_full_name }}@{{ version }}" ?? ""
body = {
"context": {
"version": "0.4.1",
"id": id,
"source": .body.release.url,
"type": "dev.cdevents.artifact.published.0.2.0",
"timestamp": ts,
# "chainId": ??
# "links": ??
},
"subject": {
"id": pkg,
"type": "artifact",
"user": sender,
}
}
}
} else if exists(.body.workflow_run) {
# https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_run
ts = parse_timestamp(.body.workflow_run.updated_at, "%+") ?? now()
ts = format_timestamp!(ts, format: "%+")
base_body = {
"context": {
"version": "0.4.1",
"id": id,
"source": .body.workflow_run.url,
"timestamp": ts,
},
"subject": {
"id": .body.workflow_run.id, # or .body.workflow_run.workflow_id ?
"type": "pipelineRun",
"content": {
"pipelineName": .body.workflow_run.name,
"url": .body.workflow_run.html_url
}
}
}
if .body.action == "requested" {
body = base_body
body.context.type = "dev.cdevents.pipelineRun.queued.0.2.0"
} else if .body.action == "in_progress" {
body = base_body
body.context.type = "dev.cdevents.pipelineRun.started.0.2.0"
} else if .body.action == "completed" {
body = base_body
body.context.type = "dev.cdevents.pipelinerun.finished.0.2.0"
body.subject.content.outcome = .body.workflow_run.conclusion # action_required, cancelled, failure, neutral, skipped, stale, success, timed_out, startup_failure, null
}
} else if exists(.body.workflow_job) {
# https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_job
base_body = {
"context": {
"version": "0.4.1",
"id": id,
"source": .body.workflow_job.url,
},
"subject": {
"id": .body.workflow_job.id, # or .body.workflow_run.workflow_id ?
"type": "taskRun",
"content": {
"taskName": .body.workflow_job.name,
"url": .body.workflow_job.html_url,
"pipelineRun": {
"id": .body.workflow_job.run_id
}
}
}
}
if .body.action == "in_progress" {
ts = parse_timestamp(.body.workflow_job.started_at, "%+") ?? now()
ts = format_timestamp!(ts, format: "%+")
body = base_body
body.context.timestamp = ts
body.context.type = "dev.cdevents.taskrun.started.0.2.0"
} else if .body.action == "completed" {
ts = parse_timestamp(.body.workflow_job.completed_at, "%+") ?? now()
ts = format_timestamp!(ts, format: "%+")
body = base_body
body.context.timestamp = ts
body.context.type = "dev.cdevents.taskrun.finished.0.2.0"
body.subject.content.outcome = .body.workflow_job.conclusion # success, failure, null, skipped, cancelled, action_required, neutral, timed_out
}
}

if body == null {
[]
} else {
[{
"metadata": .metadata,
"header": .header,
"body": body
}]
}
7 changes: 5 additions & 2 deletions charts/cdviz-collector/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@ kind: ConfigMap
metadata:
name: {{ include "my.fullname" . }}
data:
cdviz-collector.toml: |
{{- tpl .Values.config $ | nindent 4 }}
{{ (.Files.Glob "config_files/**").AsConfig | indent 2 }}
{{- range $path, $content := .Values.configFiles }}
{{ $path | quote }}: |
{{ $content | nindent 4 }}
{{- end }}
67 changes: 49 additions & 18 deletions charts/cdviz-collector/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -90,26 +90,57 @@ tolerations: []

affinity: {}

# List of config files to provide as a configMap mounted on the /etc/config folder.
# Adding & overriding files provided as part of the chart is allowed
# Content could set by override of the values
# or via `helm ... --set-file 'configFiles.config\.toml'=custom-config.toml`
# currently, the following config files are provided:
# - cdviz-collector.toml
# - cnv_github_events.vrl
configFiles:
"cdviz-collector.toml": |-
[sinks.debug]
enabled = true
[sinks.cdviz_db]
enabled = true
[sources.cdevents_webhook]
enabled = false
[sources.cdevents_webhook.extractor]
type = "webhook"
id = "000"
[sources.github_webhook]
enabled = true
transformers_ref = [ "github_events"]
[sources.github_webhook.extractor]
type = "webhook"
id = "001"
headers_to_keep = []
signature = { signature_encoding = "hex", signature_on = "body", signature_prefix = "sha256=", header = "x-hub-signature-256", token = "changeme" }
[transformers.github_events]
type = "vrl"
template_file = "/etc/config/cnv_github_events.vrl"
env:
CDVIZ_COLLECTOR__SOURCES__CDEVENTS_WEBHOOK__EXTRACTOR__HOST:
value: "0.0.0.0"
CDVIZ_COLLECTOR__SOURCES__CDEVENTS_WEBHOOK__EXTRACTOR__PORT:
RUST_LOG:
value: info
CDVIZ_COLLECTOR__HTTP__PORT:
value: "{{ .Values.service.port }}"
CDVIZ_COLLECTOR__SINKS__CDVIZ_DB__URL:
valueFrom:
secretKeyRef:
name: ""
key: DATABASE_URL

config: |
[sources.cdevents_webhook]
enabled = true
[sinks.debug]
enabled = true
[sinks.cdviz_db]
enabled = true
# CDVIZ_COLLECTOR__SINKS__CDVIZ_DB__URL:
# valueFrom:
# secretKeyRef:
# name: ""
# key: DATABASE_URL
# CDVIZ_COLLECTOR__SOURCES__GITHUB_WEBHOOK__EXTRACTOR__SIGNATURE__TOKEN:
# valueFrom:
# secretKeyRef:
# name: ""
# key: GITHUB_WEBHOOK_SIGNATURE_TOKEN

# Additional kubernetes resources to create. Helm template could be used.
# you could use it to create secrets, or custom resources like external secrets,
Expand Down
11 changes: 9 additions & 2 deletions demos/stack-k8s/values/cdviz-collector.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,24 @@ env:
CDVIZ_COLLECTOR__SINKS__CDVIZ_DB__URL:
valueFrom:
secretKeyRef:
name: "cdviz-db-collector" # secret defined below
name: "cdviz-collector" # secret defined below
key: DATABASE_URL
CDVIZ_COLLECTOR__SOURCES__GITHUB_WEBHOOK__EXTRACTOR__SIGNATURE__TOKEN:
valueFrom:
secretKeyRef:
name: "cdviz-collector"
key: GITHUB_WEBHOOK_SIGNATURE_TOKEN

extraResources:
secrets:
enabled: true
apiVersion: v1
kind: Secret
metadata:
name: cdviz-db-collector
name: cdviz-collector
type: Opaque
data:
DATABASE_URL: |-
{{ .Values.secrets.values.DATABASE_URL | default (printf "postgres://%s:%s@%s:%s/%s" .Values.secrets.values.CDVIZ_COLLECTOR_POSTGRES_USER .Values.secrets.values.CDVIZ_COLLECTOR_POSTGRES_PASSWORD .Values.secrets.values.CDVIZ_COLLECTOR_POSTGRES_HOST .Values.secrets.values.POSTGRES_PORT_NUMBER .Values.secrets.values.POSTGRES_DB) | b64enc }}
GITHUB_WEBHOOK_SIGNATURE_TOKEN: |-
{{ .Values.secrets.values.GITHUB_WEBHOOK_SIGNATURE_TOKEN | default (randAlphaNum 32) | b64enc }}
2 changes: 2 additions & 0 deletions demos/stack-k8s/values/secret.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ secrets:
CDVIZ_DASHBOARDS_POSTGRES_HOST: cdviz-db-rw.cdviz-dev.svc.cluster.local
CDVIZ_DASHBOARDS_POSTGRES_USER: cdviz
CDVIZ_DASHBOARDS_POSTGRES_PASSWORD: postgres-password
#
GITHUB_WEBHOOK_SIGNATURE_TOKEN: gh-changeme

0 comments on commit 7b1ee20

Please sign in to comment.