init
This commit is contained in:
commit
9eb9bd48c4
|
@ -0,0 +1,24 @@
|
|||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG BASE_IMAGE_ALPINE=alpine:3
|
||||
|
||||
|
||||
FROM ${BASE_IMAGE_ALPINE} AS py
|
||||
|
||||
RUN apk -v --no-progress --no-cache add --upgrade python3
|
||||
|
||||
|
||||
FROM py AS test
|
||||
|
||||
RUN apk -v --no-progress --no-cache add --upgrade py3-pytest
|
||||
|
||||
WORKDIR /src
|
||||
COPY test.py transform .
|
||||
RUN PYTHONDONTWRITEBYTECODE=1 ./test.py ./transform
|
||||
|
||||
|
||||
FROM py
|
||||
|
||||
COPY --from=test /src/transform /usr/local/bin/
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/transform"]
|
|
@ -0,0 +1,119 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Exercise the transform program.
|
||||
|
||||
Sample inputs are fed to the transform program on stdin.
|
||||
The transform program writes its output to stdout.
|
||||
This test program compares actual output with expected output,
|
||||
and exits with non-zero status upon any mismatch.
|
||||
"""
|
||||
|
||||
# This test program is automatically executed on container build.
|
||||
# Test dependencies, namely pytest, are supplied by the container image.
|
||||
#
|
||||
# This file must have a .py extension.
|
||||
# pytest maintainers refuse to allow test collection otherwise.
|
||||
|
||||
# pylint: disable=missing-function-docstring
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import subprocess
|
||||
from contextlib import ExitStack
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def test_null():
|
||||
assert run_prog([]) == []
|
||||
|
||||
|
||||
def test_ignores_plumbing_branch():
|
||||
assert run_prog([{"name": "plumbing"}]) == []
|
||||
|
||||
|
||||
def test_ignores_trunkish_branch():
|
||||
assert (run_prog([{"name": "main"},
|
||||
{"name": "master"}])
|
||||
== [])
|
||||
|
||||
|
||||
def test_topic_branch():
|
||||
assert (run_prog([{"name": "bobtest"}])
|
||||
==
|
||||
[{"name": "bobtest",
|
||||
"tag": "bobtest"}])
|
||||
assert (run_prog([{"name": "bob-test"}])
|
||||
==
|
||||
[{"name": "bob-test",
|
||||
"tag": "bob-test"}])
|
||||
|
||||
# use - as a substitute for characters that would not be valid in a tag
|
||||
assert (run_prog([{"name": "bob/frob"}])
|
||||
==
|
||||
[{"name": "bob/frob",
|
||||
"tag": "bob-frob"}])
|
||||
assert (run_prog([{"name": "bob/-frob"}])
|
||||
==
|
||||
[{"name": "bob/-frob",
|
||||
"tag": "bob-frob"}])
|
||||
|
||||
|
||||
PROG = os.environ.get("TEST_PROG") # see bottom
|
||||
|
||||
|
||||
def run_prog(input_obj):
|
||||
with ExitStack() as st:
|
||||
fi = st.enter_context(tempfile.TemporaryFile(mode="w+", encoding="utf8"))
|
||||
fo = st.enter_context(tempfile.TemporaryFile(mode="w+", encoding="utf8"))
|
||||
json.dump(input_obj, fi)
|
||||
fi.seek(0)
|
||||
subprocess.run([PROG], stdin=fi, stdout=fo, check=True)
|
||||
fo.seek(0)
|
||||
return json.load(fo)
|
||||
|
||||
|
||||
class Args:
|
||||
|
||||
@classmethod
|
||||
def parse(cls, argv=None):
|
||||
if argv is None:
|
||||
argv = sys.argv
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("transform-prog",
|
||||
help="Path to the program under test.")
|
||||
args = parser.parse_args(argv[1:])
|
||||
return cls(args)
|
||||
|
||||
def __init__(self, args):
|
||||
self._args = args
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self._args, name)
|
||||
|
||||
@property
|
||||
def prog(self):
|
||||
return getattr(self, "transform-prog")
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
if not argv:
|
||||
argv = sys.argv
|
||||
# Global bindings we make here are not visible when pytest is executing,
|
||||
# probably because it (re)imports the module. ¯\_(ツ)_/¯
|
||||
# Funnel whatever we need through the process environment instead.
|
||||
args = Args.parse(argv)
|
||||
os.environ["TEST_PROG"] = args.prog
|
||||
return pytest.main(["-vv", # dump full structured diffs upon any mismatch
|
||||
"-o", "console_output_style=classic",
|
||||
# suppress useless progress markers
|
||||
"--tb=short", # suppress outrageously verbose tracebacks
|
||||
argv[0]])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv))
|
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# pylint: disable=missing-function-docstring
|
||||
# pylint: disable=missing-module-docstring
|
||||
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
def main(unused_argv=None):
|
||||
# https://github.com/aoldershaw/git-branches-resource
|
||||
# see branches.json
|
||||
# JSON array of objects containing the field 'name'
|
||||
input_obj = json.load(sys.stdin)
|
||||
|
||||
all_branches = [b.get("name") for b in input_obj]
|
||||
|
||||
topic_branches = [name for name in all_branches
|
||||
if name not in ("main", "master", "plumbing")]
|
||||
|
||||
output_obj = [{"name": name, "tag": tag_from_branch(name)}
|
||||
for name in topic_branches]
|
||||
|
||||
json.dump(output_obj, sys.stdout)
|
||||
|
||||
|
||||
PAT_UNSAFE_TAG = re.compile(r"[^0-9a-zA-Z.-]", flags=re.ASCII)
|
||||
PAT_HYPHEN_MINUS_RUN = re.compile(r"--+")
|
||||
|
||||
def tag_from_branch(branch):
|
||||
return patsubsts(branch, ((PAT_UNSAFE_TAG, "-"),
|
||||
(PAT_HYPHEN_MINUS_RUN, "-")))
|
||||
|
||||
|
||||
def patsubsts(s, patsubs):
|
||||
for pat, sub in patsubs:
|
||||
s = pat.sub(sub, s)
|
||||
return s
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv))
|
|
@ -0,0 +1,29 @@
|
|||
# SECURITY
|
||||
# This is a public repository. Mind what you write.
|
||||
# Do not accept modifications from people outside CDCK.
|
||||
# Seek infra security review if unsure.
|
||||
|
||||
---
|
||||
resources:
|
||||
- name: discourse-auth-proxy
|
||||
type: git
|
||||
icon: github
|
||||
source:
|
||||
uri: git@github.com:discourse/discourse-auth-proxy.git
|
||||
branch: ((branch))
|
||||
paths: [dist/concourse/pipeline-branch.yaml]
|
||||
private_key: ((github-discoursebuild))
|
||||
webhook_token: unused-but-some-value-required
|
||||
|
||||
jobs:
|
||||
- name: set-branch-pipeline
|
||||
plan:
|
||||
- get: discourse-auth-proxy
|
||||
trigger: true
|
||||
- set_pipeline: auth-proxy-branch
|
||||
file: discourse-auth-proxy/dist/concourse/pipeline-branch.yaml
|
||||
instance_vars:
|
||||
branch: ((branch))
|
||||
vars:
|
||||
image_repository: auth-proxy/test
|
||||
image_tag: ((image_tag))
|
|
@ -0,0 +1,166 @@
|
|||
# SECURITY
|
||||
# This is a public repository. Mind what you write.
|
||||
# Do not accept modifications from people outside CDCK.
|
||||
# Seek infra security review if unsure.
|
||||
|
||||
---
|
||||
var_sources:
|
||||
- name: xacco
|
||||
type: vault
|
||||
config:
|
||||
url: http://127.0.0.1:8200
|
||||
path_prefix: /aws-xacc-obfuscate
|
||||
client_token: unused-but-some-value-required
|
||||
|
||||
resource_types:
|
||||
- name: git-branches
|
||||
type: registry-image
|
||||
source:
|
||||
repository: practical-concourse/resource-types/git-branches
|
||||
aws_access_key_id: ((xacco:machine/concourse-ecr-pull/docker-registry.AWS_ACCESS_KEY_ID))
|
||||
aws_secret_access_key: ((xacco:machine/concourse-ecr-pull/docker-registry.AWS_SECRET_ACCESS_KEY))
|
||||
aws_session_token: ((xacco:machine/concourse-ecr-pull/docker-registry.AWS_SESSION_TOKEN))
|
||||
aws_region: ((obfuscate-aws-docker-registry.region))
|
||||
|
||||
resources:
|
||||
- name: branches
|
||||
type: git-branches
|
||||
icon: github
|
||||
source:
|
||||
uri: git@github.com:discourse/discourse-auth-proxy.git
|
||||
private_key: ((github-discoursebuild))
|
||||
webhook_token: unused-but-some-value-required
|
||||
|
||||
- name: trunk
|
||||
type: git
|
||||
icon: github
|
||||
source:
|
||||
uri: git@github.com:discourse/discourse-auth-proxy.git
|
||||
paths: [dist/concourse/pipeline-trunk.yaml]
|
||||
private_key: ((github-discoursebuild))
|
||||
webhook_token: unused-but-some-value-required
|
||||
|
||||
- name: plumbing
|
||||
type: git
|
||||
icon: github
|
||||
source:
|
||||
uri: git@github.com:discourse/discourse-auth-proxy.git
|
||||
branch: plumbing
|
||||
private_key: ((github-discoursebuild))
|
||||
webhook_token: unused-but-some-value-required
|
||||
|
||||
- name: alpine
|
||||
type: registry-image
|
||||
icon: docker
|
||||
check_every: 24h
|
||||
source:
|
||||
repository: alpine
|
||||
tag: "3"
|
||||
username: ((docker-hub.username))
|
||||
password: ((docker-hub.password))
|
||||
|
||||
- name: branch-transformer
|
||||
type: registry-image
|
||||
icon: docker
|
||||
source:
|
||||
repository: auth-proxy/concourse/branch-transformer
|
||||
tag: latest
|
||||
aws_access_key_id: ((xacco:machine/concourse-ecr-push/docker-registry.AWS_ACCESS_KEY_ID))
|
||||
aws_secret_access_key: ((xacco:machine/concourse-ecr-push/docker-registry.AWS_SECRET_ACCESS_KEY))
|
||||
aws_session_token: ((xacco:machine/concourse-ecr-push/docker-registry.AWS_SESSION_TOKEN))
|
||||
aws_region: ((obfuscate-aws-docker-registry.region))
|
||||
|
||||
jobs:
|
||||
- name: set-self-pipeline
|
||||
plan:
|
||||
- get: plumbing
|
||||
trigger: true
|
||||
- set_pipeline: self
|
||||
file: plumbing/concourse/plumb.yaml
|
||||
|
||||
- name: set-trunk-pipeline
|
||||
plan:
|
||||
- in_parallel:
|
||||
- get: plumbing
|
||||
trigger: true
|
||||
passed: [set-self-pipeline]
|
||||
- get: trunk
|
||||
trigger: true
|
||||
- set_pipeline: auth-proxy
|
||||
file: trunk/dist/concourse/pipeline-trunk.yaml
|
||||
|
||||
- name: build-pipeline-helpers
|
||||
plan:
|
||||
- in_parallel:
|
||||
- get: plumbing
|
||||
trigger: true
|
||||
passed: [set-self-pipeline]
|
||||
- get: alpine
|
||||
params: {format: oci}
|
||||
- task: build
|
||||
privileged: true
|
||||
output_mapping:
|
||||
image: branch-transformer
|
||||
config:
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: concourse/oci-build-task
|
||||
username: ((docker-hub.username))
|
||||
password: ((docker-hub.password))
|
||||
inputs:
|
||||
- name: alpine
|
||||
- name: plumbing
|
||||
outputs:
|
||||
- name: image
|
||||
caches:
|
||||
- path: cache
|
||||
params:
|
||||
CONTEXT: plumbing/concourse/containers/branch-transformer
|
||||
DOCKERFILE: plumbing/concourse/containers/branch-transformer/Dockerfile
|
||||
IMAGE_ARG_BASE_IMAGE_ALPINE: alpine/image.tar
|
||||
OUTPUT_OCI: true
|
||||
run:
|
||||
path: build
|
||||
- put: branch-transformer
|
||||
inputs:
|
||||
- branch-transformer
|
||||
params: {image: branch-transformer/image}
|
||||
|
||||
- name: set-branch-pipelines
|
||||
plan:
|
||||
- in_parallel:
|
||||
- get: branches
|
||||
trigger: true
|
||||
- get: plumbing
|
||||
trigger: true
|
||||
passed:
|
||||
- build-pipeline-helpers
|
||||
- get: branch-transformer
|
||||
passed: [build-pipeline-helpers]
|
||||
- task: transform
|
||||
image: branch-transformer
|
||||
config:
|
||||
platform: linux
|
||||
inputs:
|
||||
- name: branches
|
||||
outputs:
|
||||
- name: transformed
|
||||
run:
|
||||
path: sh
|
||||
args:
|
||||
- -exc
|
||||
- |
|
||||
exec /usr/local/bin/transform < branches/branches.json > transformed/branches.json
|
||||
- load_var: branches
|
||||
file: transformed/branches.json
|
||||
- across:
|
||||
- var: branch
|
||||
values: ((.:branches))
|
||||
set_pipeline: plumb-auth-proxy-branch
|
||||
file: plumbing/concourse/plumb-branch.yaml
|
||||
instance_vars:
|
||||
branch: ((.:branch.name))
|
||||
vars:
|
||||
image_tag: ((.:branch.tag))
|
Loading…
Reference in New Issue