Compare commits

..

48 Commits

Author SHA1 Message Date
Tom Alexander
330a80c8b5 Fix loading the PGP WKD and AST explorer into the homepage image.
All checks were successful
semver Build semver has succeeded
build-staging Build build-staging has succeeded
build Build build has succeeded
2025-01-12 18:11:04 -05:00
Tom Alexander
6ab922beed Add back in docker targets.
All checks were successful
semver Build semver has succeeded
build Build build has succeeded
build-staging Build build-staging has succeeded
2024-10-20 23:14:04 -04:00
Tom Alexander
98161251e3 Update version of BuiltKit task.
All checks were successful
semver Build semver has succeeded
build Build build has succeeded
build-staging Build build-staging has succeeded
This version does not launch the ssh agent if no keys are mounted.
2024-10-20 21:52:06 -04:00
Tom Alexander
1422b00208 Merge branch 'buildkit'
All checks were successful
semver Build semver has succeeded
build-staging Build build-staging has succeeded
build Build build has succeeded
2024-10-20 19:40:14 -04:00
Tom Alexander
2fa772934d Remove extra volumes. 2024-10-20 19:40:04 -04:00
Tom Alexander
6dbd323979 Convert production over to the new builtkit build. 2024-10-20 19:32:18 -04:00
Tom Alexander
500fd1f0c9 Update workflow. 2024-10-20 19:27:57 -04:00
Tom Alexander
8b6836ffd9 Switch to encoding the full build process in the Dockerfile.
New features added in buildkit enable us to encode the full build process in the Dockerfile which makes tekton no longer a hard dependency for building the homepage.
2024-10-20 19:09:03 -04:00
Tom Alexander
09e8c700d2 Switch to a new Tekton task I've written to use buildkit instead of kaniko to build docker images. 2024-10-20 19:09:03 -04:00
Tom Alexander
79c5c7e589 Try the latest kaniko image. 2024-10-20 19:09:03 -04:00
Tom Alexander
0e09798982 Try autoindex. 2024-10-20 19:09:03 -04:00
Tom Alexander
bcf821dc58 Try try_files. 2024-10-20 19:09:03 -04:00
Tom Alexander
6126f26694 Merge branch 'webhook_bridge'
All checks were successful
semver Build semver has succeeded
build-staging Build build-staging has succeeded
build Build build has succeeded
2024-09-30 18:51:13 -04:00
Tom Alexander
d31c85dc44 Switch to using webhook_bridge instead of lighthouse to trigger the CI.
All checks were successful
build-staging Build build-staging has succeeded
2024-09-30 18:48:07 -04:00
Tom Alexander
4da6261cc1 Include name in resume file. 2024-07-14 12:15:41 -04:00
Tom Alexander
f4a9f4c176 Merge branch 'semver'
All checks were successful
semver Build semver has succeeded
build-homepage-staging Build build-homepage-staging has succeeded
build-homepage Build build-homepage has succeeded
2024-04-23 23:00:07 -04:00
Tom Alexander
69e36b1ad6 Inline the semver pipeline. 2024-04-23 22:59:46 -04:00
Tom Alexander
83cf479342 Update alpine.
All checks were successful
build-homepage-staging Build build-homepage-staging has succeeded
build-homepage Build build-homepage has succeeded
2024-04-23 22:15:02 -04:00
Tom Alexander
3954f1a2ae Force a build to roll out organic ast explorer changes.
All checks were successful
semver Build semver has succeeded
build-homepage-staging Build build-homepage-staging has succeeded
build-homepage Build build-homepage has succeeded
2024-01-28 19:12:14 -05:00
Tom Alexander
32a5a75c45 Force a build to roll out organic ast explorer changes.
All checks were successful
semver Build semver has succeeded
build-homepage Build build-homepage has succeeded
build-homepage-staging Build build-homepage-staging has succeeded
2024-01-28 18:32:56 -05:00
Tom Alexander
0cefdffa05 Force a build to roll out organic ast explorer changes.
All checks were successful
semver Build semver has succeeded
build-homepage-staging Build build-homepage-staging has succeeded
build-homepage Build build-homepage has succeeded
2024-01-28 17:19:53 -05:00
Tom Alexander
c8d72176c8 Force a build to roll out organic ast explorer changes.
All checks were successful
semver Build semver has succeeded
build-homepage-staging Build build-homepage-staging has succeeded
build-homepage Build build-homepage has succeeded
2024-01-28 02:04:50 -05:00
Tom Alexander
ee29c4f795 Force a build to roll out organic ast explorer changes.
All checks were successful
semver Build semver has succeeded
build-homepage-staging Build build-homepage-staging has succeeded
build-homepage Build build-homepage has succeeded
2024-01-28 01:18:02 -05:00
Tom Alexander
1cfaebd377 Merge branch 'organic_ast_explorer'
All checks were successful
semver Build semver has succeeded
build-homepage-staging Build build-homepage-staging has succeeded
build-homepage Build build-homepage has succeeded
2024-01-28 00:31:09 -05:00
Tom Alexander
d7c2a34c8e Add the organic AST explorer to the CI builds for the homepage. 2024-01-28 00:30:42 -05:00
Tom Alexander
57dd72fb91 Add a direct route for wkd also.
All checks were successful
semver Build semver has succeeded
build-homepage-staging Build build-homepage-staging has succeeded
build-homepage Build build-homepage has succeeded
I think we can reuse the files for the advanced layout by redirecting to the fizz.buzz directory.
2024-01-02 21:28:43 -05:00
Tom Alexander
ad73c7e3c5 Fix regex for pgp wkd.
All checks were successful
semver Build semver has succeeded
build-homepage-staging Build build-homepage-staging has succeeded
build-homepage Build build-homepage has succeeded
2024-01-02 13:40:12 -05:00
Tom Alexander
e2451c7510 Separate out the locations in well-known again.
All checks were successful
semver Build semver has succeeded
build-homepage-staging Build build-homepage-staging has succeeded
build-homepage Build build-homepage has succeeded
2024-01-02 13:35:55 -05:00
Tom Alexander
1633099428 Update the nginx config to use a single well-known location block.
All checks were successful
semver Build semver has succeeded
build-homepage-staging Build build-homepage-staging has succeeded
build-homepage Build build-homepage has succeeded
2024-01-02 13:33:24 -05:00
Tom Alexander
d214244217 Inline the pipeline for building for the full homepage.
All checks were successful
semver Build semver has succeeded
build-homepage-staging Build build-homepage-staging has succeeded
build-homepage Build build-homepage has succeeded
Previously, this was using a pre-defined pipeline that had to be loaded into the kubernetes context before this ran. Now, the pipeline is inlined with resolvers for the various tasks used from the catalog.
2024-01-02 13:12:23 -05:00
Tom Alexander
ac736c1ec6 Merge branch 'wkd'
All checks were successful
semver Build semver has succeeded
build-homepage Build build-homepage has succeeded
build-homepage-staging Build build-homepage-staging has succeeded
2024-01-02 12:52:37 -05:00
Tom Alexander
ce6d2d4442 Add a build step to clone the private homepage files.
This is currently used to deploy a PGP WKD (Web Key Directory) for my PGP keys.
2024-01-02 12:52:00 -05:00
Tom Alexander
81a5788ba9 Merge branch 'natter'
All checks were successful
semver Build semver has succeeded
build-homepage Build build-homepage has succeeded
build-homepage-staging Build build-homepage-staging has succeeded
2023-12-23 23:13:44 -05:00
Tom Alexander
8918dd124b Add .gitignore file.
All checks were successful
build-homepage-staging Build build-homepage-staging has succeeded
2023-12-23 19:32:38 -05:00
Tom Alexander
19cb4dcea8 Remove the title.
All checks were successful
build-homepage-staging Build build-homepage-staging has succeeded
2023-12-23 19:23:10 -05:00
Tom Alexander
d5b6b93f71 Replace the static html homepage with an org page.
All checks were successful
build-homepage-staging Build build-homepage-staging has succeeded
2023-12-23 19:00:34 -05:00
Tom Alexander
a70809ddbb Add docker ignore file.
All checks were successful
build-homepage-staging Build build-homepage-staging has succeeded
2023-12-23 17:50:56 -05:00
Tom Alexander
3c2cff0cef Use resolvers for tasks.
All checks were successful
build-homepage-staging Build build-homepage-staging has succeeded
2023-12-23 17:49:07 -05:00
Tom Alexander
3ebe169ee9 Add a CI job to build the staging image of the homepage.
All checks were successful
build-homepage-staging Build build-homepage-staging has succeeded
The staging image will be whatever commit was most recently pushed, deployed instantly to a protected subdomain.
2023-12-23 17:46:10 -05:00
Tom Alexander
070eaef72d Update homepage repo to build using natter. 2023-12-23 17:27:42 -05:00
Tom Alexander
a78b4eb7c4 Modernize the makefile for the docker image.
All checks were successful
build-homepage Build build-homepage has succeeded
semver Build semver has succeeded
2023-12-23 06:27:37 -05:00
Tom Alexander
9ebcf96ed2 Change default mime type inside .well-known to be plain text.
All checks were successful
semver Build semver has succeeded
build-homepage Build build-homepage has succeeded
2023-09-23 12:36:58 -04:00
Tom Alexander
846da7bcf9 Move well-known to not be hidden. Nginx will handle rewriting the path.
All checks were successful
semver Build semver has succeeded
build-homepage Build build-homepage has succeeded
2023-09-23 12:29:31 -04:00
Tom Alexander
ae7240b2f4 Render my public pgp key in the browser instead of downloading it.
All checks were successful
semver Build semver has succeeded
build-homepage Build build-homepage has succeeded
2023-09-21 23:18:37 -04:00
Tom Alexander
cee38a2c55 Remove extra subkey from pgp key.
All checks were successful
semver Build semver has succeeded
build-homepage Build build-homepage has succeeded
2023-09-21 16:30:03 -04:00
Tom Alexander
e96557998e Update pgp public key.
All checks were successful
semver Build semver has succeeded
build-homepage Build build-homepage has succeeded
2023-09-21 13:29:21 -04:00
Tom Alexander
2781f8f726 Disable quirks mode for html.
All checks were successful
semver Build semver has succeeded
build-homepage Build build-homepage has succeeded
2023-08-27 21:34:35 -04:00
Tom Alexander
3343a338e2 Add CORS header to well-known matrix endpoints.
All checks were successful
semver Build semver has succeeded
build-homepage Build build-homepage has succeeded
2023-08-10 14:44:00 -04:00
16 changed files with 863 additions and 147 deletions

2
.dockerignore Normal file
View File

@@ -0,0 +1,2 @@
**/.git
**/.gitignore

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
output/

View File

@@ -1,63 +0,0 @@
apiVersion: config.lighthouse.jenkins-x.io/v1alpha1
kind: TriggerConfig
spec:
postsubmits:
- name: semver
agent: tekton-pipeline
branches:
- ^main$
- ^master$
context: homepage
max_concurrency: 1
# Override https-based url from lighthouse events.
clone_uri: "git@code.fizz.buzz:talexander/homepage.git"
pipeline_run_spec:
serviceAccountName: build-bot
pipelineRef:
name: semver
namespace: lighthouse
workspaces:
- name: git-source
volumeClaimTemplate:
spec:
storageClassName: "nfs-client"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
subPath: homepage-source
params: []
- name: build-homepage
agent: tekton-pipeline
branches:
- "^v[0-9]+\\.[0-9]+\\.[0-9]+$"
context: build-docker
max_concurrency: 1
# Override https-based url from lighthouse events.
clone_uri: "git@code.fizz.buzz:talexander/homepage.git"
pipeline_run_spec:
serviceAccountName: build-bot
pipelineRef:
name: build-docker-pipeline
workspaces:
- name: git-source
volumeClaimTemplate:
spec:
storageClassName: "nfs-client"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
subPath: git-source
- name: docker-credentials
secret:
secretName: harbor-plain
params:
- name: image-name
value: "harbor.fizz.buzz/private/homepage"
- name: path-to-image-context
value: .
- name: path-to-dockerfile
value: docker/server/Dockerfile

View File

@@ -0,0 +1,246 @@
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: build-homepage-staging
spec:
timeouts:
pipeline: "2h0m0s"
tasks: "1h0m0s"
finally: "0h30m0s"
taskRunTemplate:
serviceAccountName: build-bot
pipelineSpec:
params:
- name: image-name
description: The name for the built image
type: string
- name: target-name
description: The dockerfile target to build
type: string
- name: path-to-image-context
description: The path to the build context
type: string
- name: path-to-dockerfile
description: The path to the Dockerfile
type: string
tasks:
- name: get-time
taskSpec:
metadata: {}
stepTemplate:
image: alpine:3.20
computeResources:
requests:
cpu: 10m
memory: 600Mi
workingDir: "/"
results:
- name: unix-time
description: The current date in unix timestamp format.
steps:
- image: alpine:3.20
name: get-time-step
script: |
#!/usr/bin/env sh
set -euo pipefail
echo -n "$(date +%s)" | tee $(results.unix-time.path)
- name: get-git-commit-time
taskSpec:
metadata: {}
stepTemplate:
image: alpine:3.20
computeResources:
requests:
cpu: 10m
memory: 600Mi
workingDir: "$(workspaces.repo.path)"
results:
- name: unix-time
description: The time of the git commit in unix timestamp format.
steps:
- image: alpine/git:v2.34.2
name: detect-tag-step
script: |
#!/usr/bin/env sh
set -euo pipefail
echo -n "$(git log -1 --pretty=%ct)" | tee $(results.unix-time.path)
workspaces:
- name: repo
workspace: git-source
runAfter:
- fetch-repository
- name: report-pending
taskRef:
resolver: git
params:
- name: url
value: https://code.fizz.buzz/mirror/catalog.git # mirror of https://github.com/tektoncd/catalog.git
- name: revision
value: df36b3853a5657fd883015cdbf07ad6466918acf
- name: pathInRepo
value: task/gitea-set-status/0.1/gitea-set-status.yaml
runAfter:
- fetch-repository
params:
- name: CONTEXT
value: "$(params.JOB_NAME)"
- name: REPO_FULL_NAME
value: "$(params.REPO_OWNER)/$(params.REPO_NAME)"
- name: GITEA_HOST_URL
value: code.fizz.buzz
- name: SHA
value: "$(tasks.fetch-repository.results.commit)"
- name: DESCRIPTION
value: "Build $(params.JOB_NAME) has started"
- name: STATE
value: pending
- name: TARGET_URL
value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)"
- name: fetch-repository
taskRef:
resolver: git
params:
- name: url
value: https://code.fizz.buzz/mirror/catalog.git # mirror of https://github.com/tektoncd/catalog.git
- name: revision
value: df36b3853a5657fd883015cdbf07ad6466918acf
- name: pathInRepo
value: task/git-clone/0.9/git-clone.yaml
workspaces:
- name: output
workspace: git-source
params:
- name: url
value: $(params.REPO_URL)
- name: revision
value: $(params.PULL_BASE_SHA)
- name: deleteExisting
value: "true"
- name: build-image
taskRef:
resolver: git
params:
- name: url
value: https://code.fizz.buzz/talexander/personal_tekton_catalog.git
- name: revision
value: 7ee31a185243ee6da13dcd26a592c585b64c80e5
- name: pathInRepo
value: task/buildkit-rootless-daemonless/0.1/buildkit-rootless-daemonless.yaml
params:
- name: OUTPUT
value: >-
type=image,"name=$(params.image-name):latest,$(params.image-name):$(tasks.get-time.results.unix-time)",push=true,compression=zstd,compression-level=22,oci-mediatypes=true
- name: CONTEXT
value: $(params.path-to-image-context)
- name: DOCKERFILE
value: $(params.path-to-dockerfile)
- name: EXTRA_ARGS
value:
- "--opt"
- "target=$(params.target-name)"
- --import-cache
- "type=registry,ref=$(params.image-name):buildcache"
- --export-cache
- "type=registry,ref=$(params.image-name):buildcache,mode=max,compression=zstd,compression-level=22,rewrite-timestamp=true,image-manifest=true,oci-mediatypes=true"
- --opt
- build-arg:SOURCE_DATE_EPOCH=$(tasks.get-git-commit-time.results.unix-time)
- name: BUILDKITD_TOML
value: |
debug = true
[registry."docker.io"]
mirrors = ["dockerhub.dockerhub.svc.cluster.local"]
[registry."dockerhub.dockerhub.svc.cluster.local"]
http = true
insecure = true
workspaces:
- name: source
workspace: git-source
- name: dockerconfig
workspace: docker-credentials
runAfter:
- fetch-repository
finally:
- name: report-success
when:
- input: "$(tasks.status)"
operator: in
values: ["Succeeded", "Completed"]
taskRef:
resolver: git
params:
- name: url
value: https://code.fizz.buzz/mirror/catalog.git # mirror of https://github.com/tektoncd/catalog.git
- name: revision
value: df36b3853a5657fd883015cdbf07ad6466918acf
- name: pathInRepo
value: task/gitea-set-status/0.1/gitea-set-status.yaml
params:
- name: CONTEXT
value: "$(params.JOB_NAME)"
- name: REPO_FULL_NAME
value: "$(params.REPO_OWNER)/$(params.REPO_NAME)"
- name: GITEA_HOST_URL
value: code.fizz.buzz
- name: SHA
value: "$(tasks.fetch-repository.results.commit)"
- name: DESCRIPTION
value: "Build $(params.JOB_NAME) has succeeded"
- name: STATE
value: success
- name: TARGET_URL
value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)"
- name: report-failure
when:
- input: "$(tasks.status)"
operator: in
values: ["Failed"]
taskRef:
resolver: git
params:
- name: url
value: https://code.fizz.buzz/mirror/catalog.git # mirror of https://github.com/tektoncd/catalog.git
- name: revision
value: df36b3853a5657fd883015cdbf07ad6466918acf
- name: pathInRepo
value: task/gitea-set-status/0.1/gitea-set-status.yaml
params:
- name: CONTEXT
value: "$(params.JOB_NAME)"
- name: REPO_FULL_NAME
value: "$(params.REPO_OWNER)/$(params.REPO_NAME)"
- name: GITEA_HOST_URL
value: code.fizz.buzz
- name: SHA
value: "$(tasks.fetch-repository.results.commit)"
- name: DESCRIPTION
value: "Build $(params.JOB_NAME) has failed"
- name: STATE
value: failure
- name: TARGET_URL
value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)"
workspaces:
- name: git-source
- name: docker-credentials
workspaces:
- name: git-source
volumeClaimTemplate:
spec:
storageClassName: "nfs-client"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
subPath: rust-source
- name: docker-credentials
secret:
secretName: harbor-plain
params:
- name: image-name
value: "harbor.fizz.buzz/private/homepage-staging"
- name: target-name
value: ""
- name: path-to-image-context
value: .
- name: path-to-dockerfile
value: docker/server

View File

@@ -0,0 +1,258 @@
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: build-homepage
spec:
timeouts:
pipeline: "2h0m0s"
tasks: "1h0m0s"
finally: "0h30m0s"
taskRunTemplate:
serviceAccountName: build-bot
pipelineSpec:
params:
- name: image-name
description: The name for the built image
type: string
- name: target-name
description: The dockerfile target to build
type: string
- name: path-to-image-context
description: The path to the build context
type: string
- name: path-to-dockerfile
description: The path to the Dockerfile
type: string
tasks:
- name: get-git-commit-time
taskSpec:
metadata: {}
stepTemplate:
image: alpine:3.20
computeResources:
requests:
cpu: 10m
memory: 600Mi
workingDir: "$(workspaces.repo.path)"
results:
- name: unix-time
description: The time of the git commit in unix timestamp format.
steps:
- image: alpine/git:v2.34.2
name: detect-tag-step
script: |
#!/usr/bin/env sh
set -euo pipefail
echo -n "$(git log -1 --pretty=%ct)" | tee $(results.unix-time.path)
workspaces:
- name: repo
workspace: git-source
runAfter:
- fetch-repository
- name: detect-tag
taskSpec:
metadata: {}
stepTemplate:
image: alpine:3.20
computeResources:
requests:
cpu: 10m
memory: 600Mi
workingDir: "$(workspaces.repo.path)"
results:
- name: tag
description: The tag to use for the docker container.
steps:
- image: alpine/git:v2.34.2
name: detect-tag-step
script: |
#!/usr/bin/env sh
set -euo pipefail
git fetch --tags
current_tag=$(git tag --points-at HEAD --list 'v*.*.*')
if [ -z "$current_tag" ]; then
echo "No tag at current commit"
exit 1
else
echo -n "${current_tag}" | tee $(results.tag.path)
fi
workspaces:
- name: repo
workspace: git-source
runAfter:
- fetch-repository
- name: report-pending
taskRef:
resolver: git
params:
- name: url
value: https://code.fizz.buzz/mirror/catalog.git # mirror of https://github.com/tektoncd/catalog.git
- name: revision
value: df36b3853a5657fd883015cdbf07ad6466918acf
- name: pathInRepo
value: task/gitea-set-status/0.1/gitea-set-status.yaml
runAfter:
- fetch-repository
params:
- name: CONTEXT
value: "$(params.JOB_NAME)"
- name: REPO_FULL_NAME
value: "$(params.REPO_OWNER)/$(params.REPO_NAME)"
- name: GITEA_HOST_URL
value: code.fizz.buzz
- name: SHA
value: "$(tasks.fetch-repository.results.commit)"
- name: DESCRIPTION
value: "Build $(params.JOB_NAME) has started"
- name: STATE
value: pending
- name: TARGET_URL
value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)"
- name: fetch-repository
taskRef:
resolver: git
params:
- name: url
value: https://code.fizz.buzz/mirror/catalog.git # mirror of https://github.com/tektoncd/catalog.git
- name: revision
value: df36b3853a5657fd883015cdbf07ad6466918acf
- name: pathInRepo
value: task/git-clone/0.9/git-clone.yaml
workspaces:
- name: output
workspace: git-source
params:
- name: url
value: $(params.REPO_URL)
- name: revision
value: $(params.PULL_BASE_SHA)
- name: deleteExisting
value: "true"
- name: build-image
taskRef:
resolver: git
params:
- name: url
value: https://code.fizz.buzz/talexander/personal_tekton_catalog.git
- name: revision
value: 7ee31a185243ee6da13dcd26a592c585b64c80e5
- name: pathInRepo
value: task/buildkit-rootless-daemonless/0.1/buildkit-rootless-daemonless.yaml
params:
- name: OUTPUT
value: >-
type=image,"name=$(params.image-name):latest,$(params.image-name):$(tasks.detect-tag.results.tag)",push=true,compression=zstd,compression-level=22,oci-mediatypes=true
- name: CONTEXT
value: $(params.path-to-image-context)
- name: DOCKERFILE
value: $(params.path-to-dockerfile)
- name: EXTRA_ARGS
value:
- "--opt"
- "target=$(params.target-name)"
- --import-cache
- "type=registry,ref=$(params.image-name):buildcache"
- --export-cache
- "type=registry,ref=$(params.image-name):buildcache,mode=max,compression=zstd,compression-level=22,rewrite-timestamp=true,image-manifest=true,oci-mediatypes=true"
- --opt
- build-arg:SOURCE_DATE_EPOCH=$(tasks.get-git-commit-time.results.unix-time)
- name: BUILDKITD_TOML
value: |
debug = true
[registry."docker.io"]
mirrors = ["dockerhub.dockerhub.svc.cluster.local"]
[registry."dockerhub.dockerhub.svc.cluster.local"]
http = true
insecure = true
workspaces:
- name: source
workspace: git-source
- name: dockerconfig
workspace: docker-credentials
runAfter:
- fetch-repository
finally:
- name: report-success
when:
- input: "$(tasks.status)"
operator: in
values: ["Succeeded", "Completed"]
taskRef:
resolver: git
params:
- name: url
value: https://code.fizz.buzz/mirror/catalog.git # mirror of https://github.com/tektoncd/catalog.git
- name: revision
value: df36b3853a5657fd883015cdbf07ad6466918acf
- name: pathInRepo
value: task/gitea-set-status/0.1/gitea-set-status.yaml
params:
- name: CONTEXT
value: "$(params.JOB_NAME)"
- name: REPO_FULL_NAME
value: "$(params.REPO_OWNER)/$(params.REPO_NAME)"
- name: GITEA_HOST_URL
value: code.fizz.buzz
- name: SHA
value: "$(tasks.fetch-repository.results.commit)"
- name: DESCRIPTION
value: "Build $(params.JOB_NAME) has succeeded"
- name: STATE
value: success
- name: TARGET_URL
value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)"
- name: report-failure
when:
- input: "$(tasks.status)"
operator: in
values: ["Failed"]
taskRef:
resolver: git
params:
- name: url
value: https://code.fizz.buzz/mirror/catalog.git # mirror of https://github.com/tektoncd/catalog.git
- name: revision
value: df36b3853a5657fd883015cdbf07ad6466918acf
- name: pathInRepo
value: task/gitea-set-status/0.1/gitea-set-status.yaml
params:
- name: CONTEXT
value: "$(params.JOB_NAME)"
- name: REPO_FULL_NAME
value: "$(params.REPO_OWNER)/$(params.REPO_NAME)"
- name: GITEA_HOST_URL
value: code.fizz.buzz
- name: SHA
value: "$(tasks.fetch-repository.results.commit)"
- name: DESCRIPTION
value: "Build $(params.JOB_NAME) has failed"
- name: STATE
value: failure
- name: TARGET_URL
value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)"
workspaces:
- name: git-source
- name: docker-credentials
workspaces:
- name: git-source
volumeClaimTemplate:
spec:
storageClassName: "nfs-client"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
subPath: rust-source
- name: docker-credentials
secret:
secretName: harbor-plain
params:
- name: image-name
value: "harbor.fizz.buzz/private/homepage"
- name: target-name
value: ""
- name: path-to-image-context
value: .
- name: path-to-dockerfile
value: docker/server

View File

@@ -0,0 +1,187 @@
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: semver
spec:
timeouts:
pipeline: "2h0m0s"
tasks: "1h0m0s"
finally: "0h30m0s"
taskRunTemplate:
serviceAccountName: build-bot
pipelineSpec:
params:
- name: REPO_OWNER
description: Owner of the repo on gitea
type: string
- name: REPO_NAME
description: Name of the repo on gitea
type: string
- name: PULL_BASE_SHA
description: The commit sha
type: string
- name: JOB_NAME
description: The name of the job to report to gitea
type: string
tasks:
- name: calculate-tag
runAfter:
- fetch-repository
workspaces:
- name: source
workspace: git-source
taskSpec:
metadata: {}
stepTemplate:
image: alpine:3.20
computeResources:
requests:
cpu: 10m
memory: 600Mi
workingDir: /workspace/source
results:
- name: tag
description: The tag to use for the docker container
steps:
- image: alpine/git:2.43.0
name: calculate-tag
script: |
#!/usr/bin/env sh
set -euo pipefail
git config --global --add safe.directory $(workspaces.source.path)
git fetch --tags
current_tag=$(git tag --points-at HEAD --list 'v*.*.*')
if [ -z "$current_tag" ]; then
prev_tag=$(git tag --list 'v*.*.*' | sort -V -r | head -n 1)
if [ -n "$prev_tag" ]; then
last_bit=$(echo "$prev_tag" | cut -d '.' -f 3)
incremented=$((last_bit + 1))
prefix=$(echo "$prev_tag" | grep -oE 'v[0-9]*\.[0-9]*\.')
final_tag="${prefix}${incremented}"
else
final_tag="v0.0.1"
fi
echo -n "${final_tag}" | tee $(results.tag.path)
git tag "${final_tag}"
git push origin "${final_tag}"
else
echo -n "${current_tag}" | tee $(results.tag.path)
fi
- name: report-pending
taskRef:
resolver: git
params:
- name: url
value: https://code.fizz.buzz/mirror/catalog.git # mirror of https://github.com/tektoncd/catalog.git
- name: revision
value: df36b3853a5657fd883015cdbf07ad6466918acf
- name: pathInRepo
value: task/gitea-set-status/0.1/gitea-set-status.yaml
params:
- name: CONTEXT
value: "$(params.JOB_NAME)"
- name: REPO_FULL_NAME
value: "$(params.REPO_OWNER)/$(params.REPO_NAME)"
- name: GITEA_HOST_URL
value: code.fizz.buzz
- name: SHA
value: "$(tasks.fetch-repository.results.commit)"
- name: DESCRIPTION
value: "Build $(params.JOB_NAME) has started"
- name: STATE
value: pending
- name: TARGET_URL
value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)"
- name: fetch-repository
taskRef:
resolver: git
params:
- name: url
value: https://code.fizz.buzz/mirror/catalog.git # mirror of https://github.com/tektoncd/catalog.git
- name: revision
value: df36b3853a5657fd883015cdbf07ad6466918acf
- name: pathInRepo
value: task/git-clone/0.9/git-clone.yaml
workspaces:
- name: output
workspace: git-source
params:
- name: url
value: $(params.REPO_URL)
- name: revision
value: $(params.PULL_BASE_SHA)
- name: deleteExisting
value: "true"
finally:
- name: report-success
when:
- input: "$(tasks.status)"
operator: in
values: ["Succeeded", "Completed"]
taskRef:
resolver: git
params:
- name: url
value: https://code.fizz.buzz/mirror/catalog.git # mirror of https://github.com/tektoncd/catalog.git
- name: revision
value: df36b3853a5657fd883015cdbf07ad6466918acf
- name: pathInRepo
value: task/gitea-set-status/0.1/gitea-set-status.yaml
params:
- name: CONTEXT
value: "$(params.JOB_NAME)"
- name: REPO_FULL_NAME
value: "$(params.REPO_OWNER)/$(params.REPO_NAME)"
- name: GITEA_HOST_URL
value: code.fizz.buzz
- name: SHA
value: "$(tasks.fetch-repository.results.commit)"
- name: DESCRIPTION
value: "Build $(params.JOB_NAME) has succeeded"
- name: STATE
value: success
- name: TARGET_URL
value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)"
- name: report-failure
when:
- input: "$(tasks.status)"
operator: in
values: ["Failed"]
taskRef:
resolver: git
params:
- name: url
value: https://code.fizz.buzz/mirror/catalog.git # mirror of https://github.com/tektoncd/catalog.git
- name: revision
value: df36b3853a5657fd883015cdbf07ad6466918acf
- name: pathInRepo
value: task/gitea-set-status/0.1/gitea-set-status.yaml
params:
- name: CONTEXT
value: "$(params.JOB_NAME)"
- name: REPO_FULL_NAME
value: "$(params.REPO_OWNER)/$(params.REPO_NAME)"
- name: GITEA_HOST_URL
value: code.fizz.buzz
- name: SHA
value: "$(tasks.fetch-repository.results.commit)"
- name: DESCRIPTION
value: "Build $(params.JOB_NAME) has failed"
- name: STATE
value: failure
- name: TARGET_URL
value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)"
workspaces:
- name: git-source
workspaces:
- name: git-source
volumeClaimTemplate:
spec:
storageClassName: "nfs-client"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
subPath: source
params: []

View File

@@ -0,0 +1,19 @@
version = "0.0.1"
[[push]]
name = "build"
source = "pipeline-build-homepage.yaml"
clone_uri = "git@code.fizz.buzz:talexander/homepage.git"
branches = [ "^v[0-9]+\\.[0-9]+\\.[0-9]+$" ]
[[push]]
name = "build-staging"
source = "pipeline-build-homepage-staging.yaml"
clone_uri = "git@code.fizz.buzz:talexander/homepage.git"
skip_branches = [ "^v[0-9]+\\.[0-9]+\\.[0-9]+$" ]
[[push]]
name = "semver"
source = "pipeline-semver.yaml"
clone_uri = "git@code.fizz.buzz:talexander/homepage.git"
branches = [ "^main$", "^master$" ]

View File

@@ -1,4 +1,62 @@
FROM alpine:3.18
# syntax=docker/dockerfile:1
ARG ALPINE_VERSION="3.20"
FROM scratch AS private
ADD git@code.fizz.buzz:talexander/homepage_private.git /homepage_private
FROM scratch AS explorer
ADD https://code.fizz.buzz/talexander/organic_ast_explorer.git /organic_ast_explorer
FROM scratch AS organic
ADD git@code.fizz.buzz:talexander/organic.git /organic
FROM rustlang/rust:nightly-alpine$ALPINE_VERSION AS organic-build
RUN apk add --no-cache musl-dev make bash
RUN rustup target add wasm32-unknown-unknown
RUN --mount=type=tmpfs,target=/tmp --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked cargo install wasm-bindgen-cli
COPY --link --from=organic /organic /organic
WORKDIR /organic
RUN --mount=type=tmpfs,target=/tmp --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked make wasm
FROM node:lts-alpine$ALPINE_VERSION AS explorer-build
COPY --link --from=explorer /organic_ast_explorer /organic_ast_explorer
COPY --link --from=organic-build /organic /organic
WORKDIR /organic_ast_explorer
RUN --mount=type=tmpfs,target=/tmp --mount=type=cache,target=/npmcache,sharing=locked npm set cache /npmcache && npm install
RUN npm run release
FROM rustlang/rust:nightly-alpine$ALPINE_VERSION AS natter-build
RUN apk add --no-cache musl-dev
ADD git@code.fizz.buzz:talexander/natter.git /natter
WORKDIR /natter
RUN --mount=type=tmpfs,target=/tmp --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked CARGO_TARGET_DIR=/target cargo build --profile release-lto
FROM alpine:$ALPINE_VERSION AS natter
COPY --link --from=natter-build /target/release-lto/natter /usr/bin/
COPY --link . /source
COPY --link --from=private /homepage_private/static /source/static/
COPY --link --from=explorer-build /organic_ast_explorer/dist /source/static/organic/ast_explorer/
RUN --network=none --mount=type=tmpfs,target=/tmp natter build --config /source/natter.toml
FROM alpine:$ALPINE_VERSION AS server
RUN apk add --no-cache bash nginx
RUN addgroup web && adduser -D -G web web && install -d -D -o web -g web -m 700 /srv/http/public
@@ -6,6 +64,6 @@ RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/
COPY --chown=web:web docker/server/nginx.conf /srv/http
COPY --chown=web:web docker/server/headers.include /srv/http
COPY --chown=web:web static/ /srv/http/public/
COPY --from=natter --chown=web:web /source/output/ /srv/http/public/
ENTRYPOINT ["/usr/sbin/nginx", "-c", "/srv/http/nginx.conf", "-e", "stderr", "-g", "daemon off;"]

View File

@@ -1,35 +1,52 @@
SHELL := bash
.ONESHELL:
.SHELLFLAGS := -eu -o pipefail -c
.DELETE_ON_ERROR:
MAKEFLAGS += --warn-undefined-variables
MAKEFLAGS += --no-builtin-rules
OS:=$(shell uname -s)
ifeq ($(origin .RECIPEPREFIX), undefined)
$(error This Make does not support .RECIPEPREFIX. Please use GNU Make 4.0 or later)
endif
.RECIPEPREFIX = >
IMAGE_NAME:=homepage
# REMOTE_REPO:=harbor.fizz.buzz/private
TARGET :=
.PHONY: all
all: build push
.PHONY: help
help:
> @grep -h "##" $(MAKEFILE_LIST) | grep -v grep | sed -E 's/^([^:]*): *## */\1: /'
.PHONY: build
build:
docker build -t $(IMAGE_NAME) -f Dockerfile ../
build: ## Build the docker image.
> docker build --ssh default --tag $(IMAGE_NAME) --target=$(TARGET) --file Dockerfile ../../
.PHONY: push
push:
push: ## Push the docker image to a remote repository.
ifdef REMOTE_REPO
docker tag $(IMAGE_NAME) $(REMOTE_REPO)/$(IMAGE_NAME)
docker push $(REMOTE_REPO)/$(IMAGE_NAME)
> docker tag $(IMAGE_NAME) $(REMOTE_REPO)/$(IMAGE_NAME)
> docker push $(REMOTE_REPO)/$(IMAGE_NAME)
else
@echo "REMOTE_REPO not defined, not pushing to a remote repo."
> @echo "REMOTE_REPO not defined, not pushing to a remote repo."
endif
.PHONY: clean
clean:
docker rmi $(IMAGE_NAME)
> docker rmi $(IMAGE_NAME)
ifdef REMOTE_REPO
docker rmi $(REMOTE_REPO)/$(IMAGE_NAME)
> docker rmi $(REMOTE_REPO)/$(IMAGE_NAME)
else
@echo "REMOTE_REPO not defined, not removing from remote repo."
> @echo "REMOTE_REPO not defined, not removing from remote repo."
endif
.PHONY: run
run:
docker run --rm -i -t -p "8080:8080" $(IMAGE_NAME)
run: build
run: ## Launch the docker image
> docker run --rm -i -t -p "8080:8080" $(IMAGE_NAME)
.PHONY: shell
shell:
docker run --rm -i -t -p "8080:8080" --entrypoint /bin/bash $(IMAGE_NAME)
shell: ## Launch an interactive shell inside the docker image.
shell: build
> docker run --rm -i -t -p "8080:8080" --entrypoint /bin/bash --mount type=tmpfs,destination=/tmp $(IMAGE_NAME)

View File

@@ -14,6 +14,11 @@ events {
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
types {
text/plain asc;
}
server_tokens off;
client_max_body_size 1m;
sendfile on;
@@ -26,6 +31,9 @@ http {
root /srv/http/public;
location / {
try_files $uri $uri/ =404;
autoindex on;
index index.html index.htm;
if (-d $request_filename) {
rewrite [^/]$ $http_x_forwarded_proto://$http_host$uri/ redirect;
@@ -38,13 +46,38 @@ http {
return 200 '{"status":"OK"}';
}
location /.well-known/ {
alias /srv/http/public/well-known/;
default_type text/plain;
}
location /.well-known/openpgpkey/hu/ {
alias /srv/http/public/well-known/openpgpkey/fizz.buzz/hu/;
default_type "application/octet-stream";
add_header Access-Control-Allow-Origin * always;
}
location /.well-known/openpgpkey/policy {
alias /srv/http/public/well-known/openpgpkey/fizz.buzz/policy;
default_type "application/octet-stream";
add_header Access-Control-Allow-Origin * always;
}
location ~ /\.well-known/(?<path>openpgpkey/[^/]+/hu/.*) {
alias /srv/http/public/well-known/$path;
default_type "application/octet-stream";
add_header Access-Control-Allow-Origin * always;
}
location /.well-known/matrix/server {
default_type application/json;
add_header "Access-Control-Allow-Origin" *;
return 200 '{"m.server": "matrix.fizz.buzz:8448"}';
}
location /.well-known/matrix/client {
default_type application/json;
add_header "Access-Control-Allow-Origin" *;
return 200 '{"m.homeserver":{"base_url": "https://matrix.fizz.buzz"}}';
}
}

1
natter.toml Normal file
View File

@@ -0,0 +1 @@
site_title = "FizzBuzz Blog"

24
pages/index.org Normal file
View File

@@ -0,0 +1,24 @@
#+OPTIONS: html-postamble:nil
#+date: <2023-12-23 Sat>
#+author: Tom Alexander
#+email:
#+language: en
#+select_tags: export
#+exclude_tags: noexport
My dev blog will appear here as soon as I finish writing articles worthy of publishing. In the mean time, please check out my repos at [[https://code.fizz.buzz/explore/repos][code.fizz.buzz]].
Links:
- My personal repos: [[https://code.fizz.buzz/explore/repos][code.fizz.buzz]]
- LinkedIn: https://www.linkedin.com/in/tom-alexander-b6a18216/
- GitHub: https://github.com/tomalexander
- Resume: https://fizz.buzz/tom_alexander_resume.pdf
- PGP Key: https://fizz.buzz/pgp.asc
* Why is your website the way it is?
I used to have a developer blog hosted at this domain. I quickly developed an appreciation for the power of org-mode for writing the content of the blog but I grew tired of inconsistent build results. The static site generators at the time would function by calling out to emacs itself to parse the org-mode and export HTML which meant that updates to emacs, my elisp packages, or the static site generator could cause compatibility issues. This often lead to things like escaping issues in old blog posts going unnoticed.
To solve the issue, and to seize the opportunity to gain more experience in Rust, I decided to write my own static site generator that would not depend on outside tools. So far I have written [[https://code.fizz.buzz/talexander/duster][the template engine]] and I am in the process of writing [[https://code.fizz.buzz/talexander/organic][an org-mode parser]]. When that is done, it should just be a matter of tying those two together with some minor glue to make a static site generator to create the new version of this site. Until that is done, I am using this hastily thrown-together manually-written html file as a placeholder.
That isn't to say that there are no exciting things hosted on this server, just not at the root domain. For example, this server is running kubernetes that I set up manually following [[https://github.com/kelseyhightower/kubernetes-the-hard-way][kubernetes-the-hard-way]] in a bunch of [[https://man.freebsd.org/cgi/man.cgi?bhyve][bhyve VMs]] that I networked together using [[https://man.freebsd.org/cgi/man.cgi?netgraph(4)][netgraph]]. On it I host my own [[https://www.powerdns.com/][PowerDNS]] server as the authoratative DNS server for fizz.buzz. It is integrated with [[https://cert-manager.io/][cert-manager]] and [[https://github.com/kubernetes-sigs/external-dns][ExternalDNS]] so Ingresses/LoadBalancers on my cluster automatically get valid TLS certificates and update the DNS records. I have a fully open-source self-hosted gitops workflow where a commit to a git repo I'm hosting in [[https://code.fizz.buzz/][gitea]], triggers a [[https://tekton.dev/][tekton pipeline]] through [[https://github.com/jenkins-x/lighthouse][lighthouse]] to build a docker image with [[https://github.com/GoogleContainerTools/kaniko][kaniko]], which gets pushed to my self-hosted [[https://goharbor.io/][harbor]] instance, which then gets deployed to my cluster via [[https://fluxcd.io/][flux]]. The end result is I make a commit to a repo and the result is deployed to my website in minutes.

View File

@@ -1,33 +0,0 @@
<html>
<head>
<title>FizzBuzz</title>
</head>
<body>
<h1>FizzBuzz Dev Blog.</h1>
<p><strong>Coming Eventually!</strong></p>
<br/>
<p>Please check out my repos at <a href="https://code.fizz.buzz/explore/repos">code.fizz.buzz</a>.</p>
<p>
Links
</br>
<ul>
<li>My Personal Repos: <a href="https://code.fizz.buzz/explore/repos">code.fizz.buzz</a></li>
<li>LinkedIn: <a href="https://www.linkedin.com/in/tom-alexander-b6a18216/">https://www.linkedin.com/in/tom-alexander-b6a18216/</a></li>
<li>GitHub: <a href="https://github.com/tomalexander">https://github.com/tomalexander</a></li>
<li>Resume: <a href="https://fizz.buzz/resume.pdf">https://fizz.buzz/resume.pdf</a></li>
<li>PGP Key: <a href="https://fizz.buzz/pgp.asc">https://fizz.buzz/pgp.asc</a></li>
</ul>
</p>
<h3>Why is your website the way it is?</h3>
<p>I used to have a developer blog hosted at this domain. I quickly developed an appreciation for the power of org-mode for writing the content of the blog but I grew tired of inconsistent build results. The static site generators at the time would function by calling out to emacs itself to parse the org-mode and export HTML which meant that updates to emacs, my elisp packages, or the static site generator could cause compatibility issues. This often lead to things like escaping issues in old blog posts going unnoticed.</p>
<p>To solve the issue, and to seize the opportunity to gain more experience in Rust, I decided to write my own static site generator that would not depend on outside tools. So far I have written <a href="https://code.fizz.buzz/talexander/duster">the template engine</a> and I am in the process of writing <a href="https://code.fizz.buzz/talexander/organic">an org-mode parser</a>. When that is done, it should just be a matter of tying those two together with some minor glue to make a static site generator to create the new version of this site. Until that is done, I am using this hastily thrown-together manually-written html file as a placeholder.</p>
<p>That isn't to say that there are no exciting things hosted on this server, just not at the root domain. For example, this server is running kubernetes that I set up manually following <a href="https://github.com/kelseyhightower/kubernetes-the-hard-way">kubernetes-the-hard-way</a> in a bunch of <a href="https://man.freebsd.org/cgi/man.cgi?bhyve">bhyve VMs</a> that I networked together using <a href="https://man.freebsd.org/cgi/man.cgi?netgraph(4)">netgraph</a>. On it I host my own <a href="https://www.powerdns.com/">PowerDNS</a> server as the authoratative DNS server for fizz.buzz. It is integrated with <a href="https://cert-manager.io/">cert-manager</a> and <a href="https://github.com/kubernetes-sigs/external-dns">ExternalDNS</a> so Ingresses/LoadBalancers on my cluster automatically get valid TLS certificates and update the DNS records. I have a fully open-source self-hosted gitops workflow where a commit to a git repo I'm hosting in <a href="https://code.fizz.buzz/">gitea</a>, triggers a <a href="https://tekton.dev/">tekton pipeline</a> through <a href="https://github.com/jenkins-x/lighthouse">lighthouse</a> to build a docker image with <a href="https://github.com/GoogleContainerTools/kaniko">kaniko</a>, which gets pushed to my self-hosted <a href="https://goharbor.io/">harbor</a> instance, which then gets deployed to my cluster via <a href="https://fluxcd.io/">flux</a>. The end result is I make a commit to a repo and the result is deployed to my website in minutes.</p>
</body>
</html>

View File

@@ -1,34 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mDMEXZwWGhYJKwYBBAHaRw8BAQdAfv7qozKkmf4D+5PDzADsMm4aAKDGLha7+Cu0
0H+RsWG0HVRvbSBBbGV4YW5kZXIgPHRvbUBmaXp6LmJ1eno+iJAEExYIADgWIQS4
SBWTY8KHeReVS+En3kDZuEVcGwUCXZwWGgIbAwULCQgHAgYVCAkKCwIEFgIDAQIe
AQIXgAAKCRAn3kDZuEVcG9glAQDX3Bzaz9sQpycc40LeLxSKQsWplfJigfr8wWOg
C15TywEAqkTtCrTNsltdZERLMre7qnv/6RSo54OW0C4pdN7UUAa0HlRvbSBBbGV4
YW5kZXIgPHdvcmtAZml6ei5idXp6PoiQBBMWCAA4FiEEuEgVk2PCh3kXlUvhJ95A
2bhFXBsFAl+w+R0CGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQJ95A2bhF
XBt6fgD+NOYnw9gz5K/q3H5LE/JvqzCSHezJmeGgif0CuU4m1/MA+gPDKME7syEt
JsTpELEMrxWWpDW0tD/W1iJE7roGYPQPtB9Ub20gQWxleGFuZGVyIDx0b21AaGFy
bW9uaWMuYWk+iJAEExYIADgWIQS4SBWTY8KHeReVS+En3kDZuEVcGwUCX7D5RAIb
AwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRAn3kDZuEVcGzjDAP9pM1ScstOk
ti+oRAsNSk8qsjIsCT9O5voDS0Q7plWlcwD/btKVFO9tPLsXhyvdB+NSwueVs7TA
kRVjlW3hktpefg24OARdnBYaEgorBgEEAZdVAQUBAQdArbTYQgDBMG7EBFTKA6+f
4CWgwl26Lf2b6cyCGfUw2j4DAQgHiHgEGBYIACAWIQS4SBWTY8KHeReVS+En3kDZ
uEVcGwUCXZwWGgIbDAAKCRAn3kDZuEVcG03MAQCrkjrE+MhtvbfGaHGHlwz9QnF0
Z519YzK8Xr8m0O+09QEA9BFCfkAzBM4D4JKeWJh/tmN9U6UexzLrRdY+W9cugAm4
MwRdnBbKFgkrBgEEAdpHDwEBB0A/IgvgQaDhPkk72raSlUPLZaMyJfPedlfBhbgY
uhNiSIj1BBgWCAAmAhsCFiEEuEgVk2PCh3kXlUvhJ95A2bhFXBsFAl+w+hYFCQe4
fcwAgXYgBBkWCAAdFiEEgeZEOZZ1UC6xJRa606F5yaU8Dt4FAl2cFsoACgkQ06F5
yaU8Dt6MngD+Krs3aYyHH6i85ebVESgBI8XeXhgACM4exepw+0UcoYkBAKK4DvV3
oJD6o1ku6Rr8pUH962SQm8PO9pO2JBBAb6ADCRAn3kDZuEVcG9uAAP43vUsbe24/
6tjEezAW0a4L2E1u4HNU8t53lolngs1kswEAy1HBdYEMR9TovX/kMeBHLcz1J2pM
VRSV0JnJhj5eZwa4MwRdnBcBFgkrBgEEAdpHDwEBB0BrvpOZa4q6JHVuc1XUVQTq
hDgLwD5SJBvzHSTXPYOZMoh+BBgWCAAmAhsgFiEEuEgVk2PCh3kXlUvhJ95A2bhF
XBsFAl+w+hYFCQe4fZUACgkQJ95A2bhFXBs3NgEA3SFYTgRVstidfoEpEZV4DdSL
kXaOwN3Eyba4UniClyMA/2CCxQt24vu19TyvUtOXWCp9Zi8SyIqoeiXQ4ZmhhnQO
uDgEXZwXKBIKKwYBBAGXVQEFAQEHQA7S3cFTEu6iROopVyF4UBl3hQrEAbOc9CW+
xXKFZYgSAwEIB4h+BBgWCAAmAhsMFiEEuEgVk2PCh3kXlUvhJ95A2bhFXBsFAl+w
+hcFCQe4fW4ACgkQJ95A2bhFXBtUXAEAyEJCUNVSJ7qvQv5IXuwbYTX2Mh7JU3+F
GJHO7AWBXCQA/2aLAi9kYmz9ba770XYwTeBZIv9Y6UIwIwVmFdYHC/EM
=a/z4
-----END PGP PUBLIC KEY BLOCK-----