Skip to content

Commit a8a6753

Browse files
committed
Update cookiecutter
1 parent 9477ab8 commit a8a6753

File tree

14 files changed

+396
-125
lines changed

14 files changed

+396
-125
lines changed

.ci/container_setup.d/README

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Files in this directory of the form '<number>-<name>.sh' are executed in alphabetical order.
2+
They can assume to be provided with the following environmnent variables:
3+
* PULP_CLI_CONFIG a path to a config file for the ci container
4+
* CONTAINER_RUNTIME the command for interacting with containers
5+
* BASE_PATH the directory the 'run_container.sh' script lives in
6+
7+
Also a running container named 'pulp-ephemeral'.

.ci/gen_certs.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import argparse
2+
import os
3+
import sys
4+
import typing as t
5+
6+
import trustme
7+
8+
9+
def main(argv: t.Optional[t.List[str]] = None) -> None:
10+
if argv is None:
11+
argv = sys.argv[1:]
12+
13+
parser = argparse.ArgumentParser(prog="gen_certs")
14+
parser.add_argument(
15+
"-d",
16+
"--dir",
17+
default=os.getcwd(),
18+
help="Directory where certificates and keys are written to. Defaults to cwd.",
19+
)
20+
21+
args = parser.parse_args(argv)
22+
cert_dir = args.dir
23+
24+
if not os.path.isdir(cert_dir):
25+
raise ValueError(f"--dir={cert_dir} is not a directory")
26+
27+
key_type = trustme.KeyType["ECDSA"]
28+
29+
# Generate the CA certificate
30+
ca = trustme.CA(key_type=key_type)
31+
# Write the certificate the client should trust
32+
ca_cert_path = os.path.join(cert_dir, "ca.pem")
33+
ca.cert_pem.write_to_path(path=ca_cert_path)
34+
35+
# Generate the server certificate
36+
server_cert = ca.issue_cert("localhost", "127.0.0.1", "::1", key_type=key_type)
37+
# Write the certificate and private key the server should use
38+
server_key_path = os.path.join(cert_dir, "server.key")
39+
server_cert_path = os.path.join(cert_dir, "server.pem")
40+
server_cert.private_key_pem.write_to_path(path=server_key_path)
41+
with open(server_cert_path, mode="w") as f:
42+
f.truncate()
43+
for blob in server_cert.cert_chain_pems:
44+
blob.write_to_path(path=server_cert_path, append=True)
45+
46+
# Generate the client certificate
47+
client_cert = ca.issue_cert("admin@example.com", common_name="admin", key_type=key_type)
48+
# Write the certificate and private key the client should use
49+
client_key_path = os.path.join(cert_dir, "client.key")
50+
client_cert_path = os.path.join(cert_dir, "client.pem")
51+
client_cert.private_key_pem.write_to_path(path=client_key_path)
52+
with open(client_cert_path, mode="w") as f:
53+
f.truncate()
54+
for blob in client_cert.cert_chain_pems:
55+
blob.write_to_path(path=client_cert_path, append=True)
56+
57+
58+
if __name__ == "__main__":
59+
main()

.ci/nginx.conf.j2

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# Copy from pulp-oci-images.
2+
# Ideally we can get it upstream again.
3+
#
4+
# The "nginx" package on fedora creates this user and group.
5+
user nginx nginx;
6+
# Gunicorn docs suggest this value.
7+
worker_processes 1;
8+
daemon off;
9+
events {
10+
worker_connections 1024; # increase if you have lots of clients
11+
accept_mutex off; # set to 'on' if nginx worker_processes > 1
12+
}
13+
14+
http {
15+
include mime.types;
16+
# fallback in case we can't determine a type
17+
default_type application/octet-stream;
18+
sendfile on;
19+
20+
# If left at the default of 1024, nginx emits a warning about being unable
21+
# to build optimal hash types.
22+
types_hash_max_size 4096;
23+
24+
{%- if https | default(false) %}
25+
map $ssl_client_s_dn $ssl_client_s_dn_cn {
26+
default "";
27+
~CN=(?<CN>[^,]+) $CN;
28+
}
29+
{%- endif %}
30+
31+
upstream pulp-content {
32+
server 127.0.0.1:24816;
33+
}
34+
35+
upstream pulp-api {
36+
server 127.0.0.1:24817;
37+
}
38+
39+
server {
40+
# Gunicorn docs suggest the use of the "deferred" directive on Linux.
41+
{% if https | default(false) -%}
42+
listen 443 default_server deferred ssl;
43+
44+
ssl_certificate /etc/pulp/certs/pulp_webserver.crt;
45+
ssl_certificate_key /etc/pulp/certs/pulp_webserver.key;
46+
ssl_session_cache shared:SSL:50m;
47+
ssl_session_timeout 1d;
48+
ssl_session_tickets off;
49+
50+
# intermediate configuration
51+
ssl_protocols TLSv1.2;
52+
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
53+
ssl_prefer_server_ciphers on;
54+
55+
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
56+
add_header Strict-Transport-Security max-age=15768000;
57+
58+
# Configure client cert authentication
59+
ssl_client_certificate /etc/pulp/certs/ca.pem;
60+
ssl_verify_client optional;
61+
{%- else -%}
62+
listen 80 default_server deferred;
63+
{%- endif %}
64+
server_name $hostname;
65+
66+
# The default client_max_body_size is 1m. Clients uploading
67+
# files larger than this will need to chunk said files.
68+
client_max_body_size 10m;
69+
70+
# Gunicorn docs suggest this value.
71+
keepalive_timeout 5;
72+
73+
location {{ content_path }} {
74+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
75+
proxy_set_header X-Forwarded-Proto $scheme;
76+
proxy_set_header Host $http_host;
77+
# we don't want nginx trying to do something clever with
78+
# redirects, we set the Host: header above already.
79+
proxy_redirect off;
80+
proxy_pass http://pulp-content;
81+
}
82+
83+
location {{ api_root }}api/v3/ {
84+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
85+
proxy_set_header X-Forwarded-Proto $scheme;
86+
proxy_set_header Host $http_host;
87+
{%- if https | default(false) %}
88+
proxy_set_header Remoteuser $ssl_client_s_dn_cn;
89+
{%- endif %}
90+
# we don't want nginx trying to do something clever with
91+
# redirects, we set the Host: header above already.
92+
proxy_redirect off;
93+
proxy_pass http://pulp-api;
94+
client_max_body_size 0;
95+
}
96+
97+
{%- if domain_enabled | default(false) %}
98+
location ~ {{ api_root }}.+/api/v3/ {
99+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
100+
proxy_set_header X-Forwarded-Proto $scheme;
101+
proxy_set_header Host $http_host;
102+
# we don't want nginx trying to do something clever with
103+
# redirects, we set the Host: header above already.
104+
proxy_redirect off;
105+
proxy_pass http://pulp-api;
106+
client_max_body_size 0;
107+
}
108+
{%- endif %}
109+
110+
location /auth/login/ {
111+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
112+
proxy_set_header X-Forwarded-Proto $scheme;
113+
proxy_set_header Host $http_host;
114+
# we don't want nginx trying to do something clever with
115+
# redirects, we set the Host: header above already.
116+
proxy_redirect off;
117+
proxy_pass http://pulp-api;
118+
}
119+
120+
include pulp/*.conf;
121+
122+
location / {
123+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
124+
proxy_set_header X-Forwarded-Proto $scheme;
125+
proxy_set_header Host $http_host;
126+
# we don't want nginx trying to do something clever with
127+
# redirects, we set the Host: header above already.
128+
proxy_redirect off;
129+
proxy_pass http://pulp-api;
130+
# most pulp static files are served through whitenoise
131+
# http://whitenoise.evans.io/en/stable/
132+
}
133+
134+
{%- if https | default(false) %}
135+
# ACME http-01 tokens, i.e, for Let's Encrypt
136+
location /.well-known/ {
137+
try_files $uri $uri/ =404;
138+
}
139+
{%- endif %}
140+
{% if https | default(false) -%}
141+
location /oauth2token/ {
142+
auth_basic "Tokens, Tokens, Tokens";
143+
auth_basic_user_file /etc/pulp/certs/oauth2passwd;
144+
if ($request_method !~ POST) {
145+
# This still triggers earlier than the auth_basic in the outer block.
146+
return 403;
147+
}
148+
try_files /dev/null @oauth2token;
149+
}
150+
# Nginx "return" kicks in before basic_auth, so we must use it in a separate block.
151+
# https://stackoverflow.com/questions/67975464/why-doesnt-basic-auth-work-with-a-simple-nginx-return-statement
152+
location @oauth2token {
153+
default_type application/json;
154+
charset utf-8;
155+
156+
return 200 '{"access_token": "DEADBEEF", "token_type": "bearer", "expires_in": 30}';
157+
}
158+
{%- endif %}
159+
}
160+
{%- if https | default(false) %}
161+
server {
162+
listen 80 default_server;
163+
server_name _;
164+
return 301 https://$host$request_uri;
165+
}
166+
{%- endif %}
167+
}

.ci/run_container.sh

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ then
1616
fi
1717
export CONTAINER_RUNTIME
1818

19-
TMPDIR="$(mktemp -d)"
19+
PULP_CLI_TEST_TMPDIR="$(mktemp -d)"
20+
export PULP_CLI_TEST_TMPDIR
2021

2122
cleanup () {
2223
"${CONTAINER_RUNTIME}" stop pulp-ephemeral && true
23-
rm -rf "${TMPDIR}"
24+
rm -rf "${PULP_CLI_TEST_TMPDIR}"
2425
}
2526

2627
trap cleanup EXIT
@@ -48,8 +49,9 @@ else
4849
SELINUX=""
4950
fi;
5051

51-
mkdir -p "${TMPDIR}/settings/certs"
52-
cp "${BASEPATH}/settings/settings.py" "${TMPDIR}/settings"
52+
mkdir -p "${PULP_CLI_TEST_TMPDIR}/settings/certs"
53+
cp "${BASEPATH}/settings/settings.py" "${PULP_CLI_TEST_TMPDIR}/settings/settings.py"
54+
echo "service_acct:$(openssl passwd secret)" > "${PULP_CLI_TEST_TMPDIR}/settings/certs/oauth2passwd"
5355

5456
if [ -z "${PULP_HTTPS:+x}" ]
5557
then
@@ -60,22 +62,25 @@ else
6062
PROTOCOL="https"
6163
PORT="443"
6264
PULP_CONTENT_ORIGIN="https://localhost:8080/"
63-
python3 -m trustme -d "${TMPDIR}/settings/certs"
64-
export PULP_CA_BUNDLE="${TMPDIR}/settings/certs/client.pem"
65-
ln -fs server.pem "${TMPDIR}/settings/certs/pulp_webserver.crt"
66-
ln -fs server.key "${TMPDIR}/settings/certs/pulp_webserver.key"
65+
python3 "${BASEPATH}/gen_certs.py" -d "${PULP_CLI_TEST_TMPDIR}/settings/certs"
66+
export PULP_CA_BUNDLE="${PULP_CLI_TEST_TMPDIR}/settings/certs/ca.pem"
67+
ln -fs server.pem "${PULP_CLI_TEST_TMPDIR}/settings/certs/pulp_webserver.crt"
68+
ln -fs server.key "${PULP_CLI_TEST_TMPDIR}/settings/certs/pulp_webserver.key"
6769
fi
6870
export PULP_CONTENT_ORIGIN
6971

7072
"${CONTAINER_RUNTIME}" \
7173
run ${RM:+--rm} \
7274
--env S6_KEEP_ENV=1 \
7375
${PULP_HTTPS:+--env PULP_HTTPS} \
76+
${PULP_OAUTH2:+--env PULP_OAUTH2} \
7477
${PULP_API_ROOT:+--env PULP_API_ROOT} \
7578
--env PULP_CONTENT_ORIGIN \
7679
--detach \
7780
--name "pulp-ephemeral" \
78-
--volume "${TMPDIR}/settings:/etc/pulp${SELINUX:+:Z}" \
81+
--volume "${PULP_CLI_TEST_TMPDIR}/settings:/etc/pulp${SELINUX:+:Z}" \
82+
--volume "${BASEPATH}/nginx.conf.j2:/nginx/nginx.conf.j2${SELINUX:+:Z}" \
83+
--network bridge \
7984
--publish "8080:${PORT}" \
8085
"ghcr.io/pulp/pulp:${IMAGE_TAG}"
8186

@@ -104,7 +109,7 @@ done
104109
"${CONTAINER_RUNTIME}" exec "pulp-ephemeral" pulpcore-manager reset-admin-password --password password
105110

106111
# Create pulp config
107-
PULP_CLI_CONFIG="${TMPDIR}/settings/certs/cli.toml"
112+
PULP_CLI_CONFIG="${PULP_CLI_TEST_TMPDIR}/settings/certs/cli.toml"
108113
export PULP_CLI_CONFIG
109114
pulp config create --overwrite --location "${PULP_CLI_CONFIG}" --base-url "${PROTOCOL}://localhost:8080" ${PULP_API_ROOT:+--api-root "${PULP_API_ROOT}"} --username "admin" --password "password"
110115
# show pulpcore/plugin versions we're using

.ci/scripts/pr_labels.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/bin/env python3
2+
3+
# This script is running with elevated privileges from the main branch against pull requests.
4+
5+
import re
6+
import sys
7+
import tomllib
8+
from pathlib import Path
9+
10+
from git import Repo
11+
12+
13+
def main():
14+
assert len(sys.argv) == 3
15+
16+
with open("pyproject.toml", "rb") as fp:
17+
PYPROJECT_TOML = tomllib.load(fp)
18+
BLOCKING_REGEX = re.compile(r"DRAFT|WIP|NO\s*MERGE|DO\s*NOT\s*MERGE|EXPERIMENT")
19+
ISSUE_REGEX = re.compile(r"(?:fixes|closes)[\s:]+#(\d+)")
20+
CHERRY_PICK_REGEX = re.compile(r"^\s*\(cherry picked from commit [0-9a-f]*\)\s*$")
21+
CHANGELOG_EXTS = [
22+
f".{item['directory']}" for item in PYPROJECT_TOML["tool"]["towncrier"]["type"]
23+
]
24+
25+
repo = Repo(".")
26+
27+
base_commit = repo.commit(sys.argv[1])
28+
head_commit = repo.commit(sys.argv[2])
29+
30+
pr_commits = list(repo.iter_commits(f"{base_commit}..{head_commit}"))
31+
32+
labels = {
33+
"multi-commit": len(pr_commits) > 1,
34+
"cherry-pick": False,
35+
"no-issue": False,
36+
"no-changelog": False,
37+
"wip": False,
38+
}
39+
for commit in pr_commits:
40+
labels["wip"] |= BLOCKING_REGEX.search(commit.summary) is not None
41+
no_issue = ISSUE_REGEX.search(commit.message, re.IGNORECASE) is None
42+
labels["no-issue"] |= no_issue
43+
cherry_pick = CHERRY_PICK_REGEX.search(commit.message) is not None
44+
labels["cherry-pick"] |= cherry_pick
45+
changelog_snippets = [
46+
k
47+
for k in commit.stats.files
48+
if k.startswith("CHANGES/") and Path(k).suffix in CHANGELOG_EXTS
49+
]
50+
labels["no-changelog"] |= not changelog_snippets
51+
52+
print("ADD_LABELS=" + ",".join((k for k, v in labels.items() if v)))
53+
print("REMOVE_LABELS=" + ",".join((k for k, v in labels.items() if not v)))
54+
55+
56+
if __name__ == "__main__":
57+
main()

0 commit comments

Comments
 (0)