diff --git a/app.py b/app.py index d8b37e3..de1cbaa 100755 --- a/app.py +++ b/app.py @@ -1,235 +1,416 @@ #!/usr/bin/env python3 -import git, os, shutil, json +''' +Builds and serves the documention sites of every branch +''' + +import logging +import threading +import os +import json +import sys +import signal + +from shutil import copytree, rmtree +from random import randint +from flask import Flask, Response, request + +import git +from git.exc import GitCommandError +# defaults -from flask import Flask, Response +DEFAULT_STATE_FILE='/tmp/build_state.json' +DEFAULT_WORK_PATH = "work" +DEFAULT_BUILD_ROOT = "/tmp/preview-bot/builds" +DEFAULT_REMOTE_URL = "https://github.com/CSCfi/csc-user-guide" +DEFAULT_SITE_URL = "https://csc-guide-preview.rahtiapp.fi/" +DEFAULT_SECRET = "changeme" # we are using secret but we should be utilizing whitelists +DEFAULT_PORT = 8081 -# defaults +try: + STATEFILE = os.environ["STATEFILE"] +except KeyError: + STATEFILE = '/tmp/build_state.json' + +try: + WORK_PATH = os.environ["WORKPATH"] +except KeyError: + WORK_PATH = DEFAULT_WORK_PATH -defaultWorkPath = "work" -defaultBuildRoot = "/tmp/preview-bot/builds" -defaultRemoteUrl = "https://github.com/CSCfi/csc-user-guide" -defaultSiteURL = "https://csc-guide-preview.rahtiapp.fi/" -defaultSecret = "changeme" # we are using secret but we should be utilizing whitelists -defaultPort = 8081 +try: + BUILD_ROOT = os.environ["BUILDROOT"] +except KeyError: + BUILD_ROOT = DEFAULT_BUILD_ROOT try: - workPath = os.environ["WORKPATH"] + SITE_URL = os.environ["SITEURL"] except KeyError: - workPath = defaultWorkPath + SITE_URL = DEFAULT_SITE_URL try: - buildRoot = os.environ["BUILDROOT"] + BUILD_SECRET = os.environ["BUILDSECRET"] except KeyError: - buildRoot = defaultBuildRoot + BUILD_SECRET = DEFAULT_SECRET try: - siteURL = os.environ["SITEURL"] + PORT = os.environ["PORT"] except KeyError: - siteURL = defaultSiteURL + PORT = DEFAULT_PORT try: - buildSecret = os.environ["BUILDSECRET"] + REMOTE_URL = os.environ["REMOTEURL"] except KeyError: - buildSecret = defaultSecret + REMOTE_URL = "https://github.com/CSCfi/csc-user-guide" # Configurations in CONFIGFILE will override other environment variables try: - configFile = os.environ["CONFIGFILE"] + CONFIG_FILE = os.environ["CONFIGFILE"] except KeyError: - configFile = None + CONFIG_FILE = None -# Default configuration +# Default configuration config = { - "workPath": workPath, - "remoteUrl": "https://github.com/CSCfi/csc-user-guide", - "buildRoot": buildRoot, - "debug": "False", - "secret": buildSecret, + "workPath": WORK_PATH, + "remoteUrl": REMOTE_URL, + "buildRoot": BUILD_ROOT, + "debug": "True", + "secret": BUILD_SECRET, "prune": "True" } -buildState = {} +#build_state = {} ### non-route functions -def initRepo(workPath, remote_url): - """ - Updates current repository to match `origin` remote. - Does pruning fetch. - """ - - mkdirp(workPath) +def init_repo(init_path, remote_url): + """ + Updates current repository to match `origin` remote. + Does pruning fetch. + """ - repo = git.Repo.init(workPath) + mkdirp(init_path) - try: - origin = repo.remote('origin') - except ValueError: - print("creating origin") - origin = repo.create_remote('origin', remote_url) + repo = git.Repo.init(init_path) - assert origin.exists() - assert origin == repo.remotes.origin == repo.remotes['origin'] + try: + origin = repo.remote('origin') + except ValueError: + app.logger.info(f"Creating origin {remote_url} into {init_path}") + origin = repo.create_remote('origin', remote_url) + assert origin.exists() + assert origin == repo.remotes.origin == repo.remotes['origin'] - for fetch_info in origin.fetch(None, None, prune=True): - print("Updated %s in %s" % (fetch_info.ref, fetch_info.commit)) + app.logger.info("* Fetching remote branches' content") + for fetch_info in origin.fetch(None, None, prune=True): + app.logger.info(f" Branch [{fetch_info.ref}], commit [{fetch_info.commit}]") - return repo, origin + return repo, origin def mkdirp(path): - os.makedirs(path, exist_ok=True) + ''' + Makes the dir and it does not complain if it exists + ''' + os.makedirs(path, exist_ok=True) -def buildRef(repo, ref, state): - """ - Builds and updates. - """ - global config +def build_ref(repo, ref, state): + """ + Builds and updates. + """ + #global config - print(str(ref.commit), state["built"]) - buildpath = os.path.join(config["buildRoot"], str(ref)) + buildpath = os.path.join(config["buildRoot"], str(ref)) + + app.logger.info(f"Checking [{ref}]: {str(ref.commit)} == {state['built']}") + + if os.path.isdir(buildpath) and str(ref.commit) == state["built"]: + app.logger.info(f" [{str(ref)}]: is up to date") + return + + app.logger.info(f" [{ref}] re-building {ref.commit}") + try: + repo.git.reset('--hard',ref) + except GitCommandError: + app.logger.error(f" [{str(ref)}]: cannot reset hard at this moment") - if not str(ref.commit) == state["built"] or not os.path.isdir(buildpath): - print("re-building %s in %s" % (ref, ref.commit)) - repo.git.reset('--hard',ref) repo.git.checkout(ref) - print("buildpath = %s" % (buildpath)) + app.logger.debug(f" [{ref}] buildpath = {buildpath}") + mkdirp(buildpath) + + scripts=["generate_alpha.sh", + "generate_by_system.sh", + "generate_new.sh", + "generate_glossary.sh"] + + for script in scripts: + cmd = f"sh -c 'cd {config['workPath']} && ./scripts/{script} 2>&1'" + cmdout = os.popen(cmd) + line = cmdout.readline() + app.logger.info(f" [{ref}] # {cmd}") + if cmdout.close(): + app.logger.error(f" [{ref}] {line}") + else: + app.logger.info(f" [{ref}] {line}") + + # + # WORKAROUND + with open(f"{config['workPath']}/mkdocs.yml", 'r', encoding="utf-8") as file : + filedata = file.read() + + # Replace the target string + filedata = filedata.replace(f'SITE_URL: "{SITE_URL}"', f'SITE_URL: "{SITE_URL}{str(ref)}"') + + # Write the file out again + with open(f"{config['workPath']}/mk2.yml", 'w', encoding="utf-8") as file: + file.write(filedata) + # + + cmd = f"sh -c 'cd {config['workPath']} && mkdocs build --site-dir {buildpath} -f mk2.yml 2>&1'" + app.logger.info(f" [{ref}] # %s" % (cmd)) + cmdout = os.popen(cmd) + app.logger.debug(cmdout.read()) + + cmdout.close() + + state["built"] = str(ref.commit) + +def build_commit(commit, branch): + ''' + Builds the given commit into the given branch folder. Uses a random tmp fold for the git. + ''' + + buildpath = os.path.join(config["buildRoot"], branch) + + tmp_folder = f'/tmp/{commit}-{randint(0,9999)}' + + try: + rmtree(tmp_folder) + except OSError: + pass + + copytree(config["workPath"], tmp_folder) + + repo = git.Repo.init(tmp_folder) + + repo.git.reset('--hard', commit) + repo.git.checkout(commit) + mkdirp(buildpath) scripts=["generate_alpha.sh","generate_by_system.sh","generate_new.sh","generate_glossary.sh"] for script in scripts: - cmd = "sh -c 'cd %s && ./scripts/%s 2>&1'" % (config["workPath"],script) - print("Executing: %s" % (cmd)) + cmd = f"sh -c 'cd {tmp_folder} && ./scripts/{script} 2>&1'" + print(f"Executing: {cmd}") cmdout = os.popen(cmd) print(cmdout.read()) + cmdout.close() + # # WORKAROUND - with open('%s/mkdocs.yml' % config["workPath"], 'r') as file : - filedata = file.read() + with open(f"{tmp_folder}/mkdocs.yml", 'r', encoding="utf-8") as file : + filedata = file.read() # Replace the target string - filedata = filedata.replace('site_url: "%s"' % siteURL, 'site_url: "%s%s"' % (siteURL, str(ref))) + filedata = filedata.replace(f"SITE_URL: {SITE_URL}", f'SITE_URL: "{SITE_URL}{branch}"') # Write the file out again - with open('%s/mkdocs.yml2' % config["workPath"], 'w') as file: - file.write(filedata) - # + with open(f'{tmp_folder}/mkdocs.yml2', 'w', encoding="utf-8") as file: + file.write(filedata) + # - cmd = "sh -c 'cd %s && mkdocs build --site-dir %s -f mkdocs.yml2 2>&1'" % (config["workPath"], buildpath) - print("Executing: %s" % (cmd)) + cmd = f"sh -c 'cd {tmp_folder} && mkdocs build --site-dir {buildpath} -f mkdocs.yml2 2>&1'" + print(f"Executing: {cmd}") cmdout = os.popen(cmd) print(cmdout.read()) + cmdout.close() - state["built"] = str(ref.commit) + app.logger.info("Built branch {branch} in commit {commit}") + + build_state = read_state() + + try: + build_state[str(branch)]["built"] = str(commit) + except KeyError: + build_state[str(branch)] = {"sha": str(commit), "status": "init", "built": str(commit)} + write_state(build_state) -def cleanUpZombies(): + write_state(build_state) + + rmtree(tmp_folder) + +def clean_up_zombies(): """ We want to clean all Zombies: * When spid is 0, child processes exist, but they are still alive * When ChildProcessError raises, it means that there are no children left """ - print("Cleaning up Zombies") + app.logger.info(f"* Cleaning up Zombies. This is {os.getpid()}" ) spid = -1 while spid != 0: - try: - spid, status, rusage = os.wait3(os.WNOHANG) - print("Process %d with status %d" % (spid, status)) - except ChildProcessError: - break - -def pruneBuilds(repo, origin): - repo, origin = initRepo(config["workPath"], config["remoteUrl"]) - try: - builtrefs = os.listdir(config["buildRoot"]+'/origin') - except FileNotFoundError: - print("Clean buildRoot") - return - - srefs = [str(x) for x in origin.refs] - builtrefs = ['origin/'+str(x) for x in builtrefs] - - print("Pruning old builds.") - - for bref in builtrefs: - if not bref in srefs: - print('found stale preview: ' + bref) - remove_build = remove_build=config["buildRoot"] + '/' + bref - print('Removing ' + remove_build) - shutil.rmtree(remove_build) - - print("Done pruning old builds.") + try: + spid, status, _ = os.wait3(os.WNOHANG) + app.logger.info(f"* Process {spid} with status {status}") + except ChildProcessError: + break + app.logger.info("Cleaning process done.") + +def prune_builds(origin): + ''' + Deletes any branch folder that is no longer in the repository + ''' + try: + builtrefs = os.listdir(config["buildRoot"]+'/origin') + except FileNotFoundError: + app.logger.debug("* Clean BUILD_ROOT") + return + + srefs = [str(x) for x in origin.refs] + builtrefs = ['origin/'+str(x) for x in builtrefs] + + app.logger.debug("* Pruning old builds.") + + for bref in builtrefs: + if not bref in srefs: + print(f'found stale preview: {bref}') + remove_build = config["buildRoot"] + '/' + bref + print('Removing ' + remove_build) + rmtree(remove_build) + + app.logger.debug("DONE pruning old builds.") + +def get_branch(commit): + ''' + Given a commit, it returns the corresponding branch containing the commit + ''' + repo, _ = init_repo(config["workPath"], config["remoteUrl"]) + + # Get the branch name + for ref in repo.refs: + if str(ref.commit.hexsha) == str(commit): + return ref.name + + return None ### Route functions ### app = Flask(__name__) @app.route("/build/", methods=["GET", "POST"]) -def listenBuild(secret): - global buildState - global config - - if not secret == config["secret"]: - return "Access denied" +def listen_build(secret): + ''' + This method listens to the given URL: + - Check the secret matchs + - If GET, checks all brnaches and builds the ones missing + - If POST, reads the json and builds the update branch + ''' + #global config - response = Response('built started') + if not secret == config["secret"]: + return "Access denied" - response.call_on_close(build) + if request.headers.get('Content-Type') == 'application/json': - return response + commit = request.json['after'] + branch = get_branch(commit) + if branch is None: + commit = request.json['after'] + branch = get_branch(commit) -def build(): + if branch is None: + return Response(f"Branch not found for commit {commit}") - print("Start build") + print(branch) - repo, origin = initRepo(config["workPath"], config["remoteUrl"]) + build_commit_thread = threading.Thread(target=build_commit, args=[commit, branch]) + build_commit_thread.start() - output = "" + return Response(f"{{\"commit\":\"{commit}\",\"branch\":\"{branch}\"}}" ) - # Clean buildState - for ref in origin.refs: - sref = str(ref) - output = output + "Found %s (%s)
" % (sref, str(ref.commit)) + build_thread = threading.Thread(target=build) + build_thread.start() - if not sref in buildState: - print(sref + " not found in " + str(buildState)) - buildState[sref] = {"sha": str(ref.commit), "status": "init", "built": None} + return Response('{\"built\":\"started\"}', + content_type="application/json") - # Prune nonexisting builds - if "prune" in config and config["prune"]: - pruneBuilds(repo, origin) - # Refresh builds - for ref in origin.refs: - buildRef(repo, ref, buildState[str(ref)]) - cleanUpZombies() +def build(): + ''' + Clones the repo, and makes sure that every branch is built, and prunes the deleted branches + ''' + app.logger.info("* Start build loop") + + build_state = read_state() + + repo, origin = init_repo(config["workPath"], config["remoteUrl"]) + + output = "" + + # Clean build_state + for ref in origin.refs: + sref = str(ref) + output = output + f"Found {sref} ({str(ref.commit)})
" + + if not sref in build_state: + app.logger.debug(f"Adding {sref} branch to build state") + build_state[sref] = {"sha": str(ref.commit), "status": "init", "built": None} + + # Prune nonexisting builds + if "prune" in config and config["prune"]: + prune_builds(origin) + # Refresh builds + for ref in origin.refs: + build_ref(repo, ref, build_state[str(ref)]) + write_state(build_state) + +def write_state(state): + ''' + Writes the state of the brnaches and their commits into the JSON state file + ''' + with open(STATEFILE, 'w', encoding="utf-8") as file: + json.dump(state, file) + +def read_state(): + ''' + Read the current state of bes and commits from file + ''' + try: + with open(STATEFILE, 'r', encoding="utf-8") as file: + return json.load(file) + except FileNotFoundError: + return {} + +def signal_handler(sig, frame): + clean_up_zombies() ### Entry functions if __name__=="__main__": - if not configFile == None: - print("Loading configuration from file: " + configFile) - with open(configFile) as config_file: - config = json.load(config_file) - buildSecret = config["secret"] - workPath = config["workPath"] - buildRoot = config["buildRoot"] + app.logger.setLevel(logging.INFO) + + if CONFIG_FILE is not None: + app.logger.info("Loading configuration from file: " + CONFIG_FILE) + with open(CONFIG_FILE, encoding="utf-8") as config_file: + config = json.load(config_file) + BUILD_SECRET = config["secret"] + WORK_PATH = config["workPath"] + BUILD_ROOT = config["buildRoot"] - print("workPath: " + workPath) - print("buildRoot: " + buildRoot) - print("buildSecret: " + "******") + app.logger.info("WORK_PATH: " + WORK_PATH) + app.logger.info("BUILD_ROOT: " + BUILD_ROOT) + app.logger.info("BUILD_SECRET: " + BUILD_SECRET) - if buildSecret == defaultSecret: - print("Don't use default secret since it's freely available in the internet") - exit(1) + if BUILD_SECRET == DEFAULT_SECRET: + app.logger.error("Don't use default secret since it's freely available in the internet") + sys.exit(1) - listenBuild(config["secret"]) - build() + thread = threading.Thread(target=build) + thread.start() - app.run(debug=config["debug"]=="True", - port=defaultPort, - host='0.0.0.0') + signal.signal(signal.SIGCHLD, signal_handler) + app.run(debug=config["debug"]=="True", + port=PORT, + host='0.0.0.0') diff --git a/helm/.helmignore b/helm/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/helm/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/Chart.yaml b/helm/Chart.yaml new file mode 100644 index 0000000..2dd853a --- /dev/null +++ b/helm/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: helm +description: Deploys docs-preview in Kubernetes +type: application +version: 0.2.0 +appVersion: "1.2.0" diff --git a/helm/README.md b/helm/README.md new file mode 100644 index 0000000..79e1ed8 --- /dev/null +++ b/helm/README.md @@ -0,0 +1,30 @@ +# Helm chart to deploy `docs-preview` + +> Original repository is + +This chart deploys docs-preview, which will clone a given repository (by default ), +and build every single branch in the repository. The branches will be available via a web interface. It also offers a API that understands +GitHub hooks and rebuilds the given branch by the hook. + +## Parameters + +* `values.yaml`: +```yaml +git: + source: https://github.com/cscfi/docs-preview + docs: https://github.com/cscfi/csc-user-guide +secret: + +host: csc-guide-preview.rahtiapp.fi + +replicas: 1 +``` + +|Key|Description|Default| +|:-:|:-:|:-:| +|git.source|The source (including `app.py`) to deploy|https://github.com/cscfi/docs-preview| +|git.docs|The repository hosting the documentation to build|https://github.com/cscfi/csc-user-guide| +|secret|Secret to be used in the web-hook|| +|host|URL to deploy the public web interface|`csc-guide-review.rahtiapp.fi`| +|replicas|Number of replicas for the Pod|1| + diff --git a/helm/templates/csc-guide-preview-hook-route.yaml b/helm/templates/csc-guide-preview-hook-route.yaml new file mode 100644 index 0000000..1383659 --- /dev/null +++ b/helm/templates/csc-guide-preview-hook-route.yaml @@ -0,0 +1,17 @@ +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: docs-preview-build-hook +spec: + host: {{ .Release.Namespace }}-hook.2.rahtiapp.fi + port: + targetPort: 8081 + tls: + insecureEdgeTerminationPolicy: Redirect + termination: edge + to: + kind: Service + name: docs-preview-hook + weight: 100 + wildcardPolicy: None +status: {} diff --git a/helm/templates/csc-guide-preview-route.yaml b/helm/templates/csc-guide-preview-route.yaml new file mode 100644 index 0000000..3cfedbc --- /dev/null +++ b/helm/templates/csc-guide-preview-route.yaml @@ -0,0 +1,19 @@ +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + labels: + app: docs-preview + name: docs-preview-route +spec: + host: {{ .Values.host }} + port: + targetPort: 8080-tcp + tls: + insecureEdgeTerminationPolicy: Redirect + termination: edge + to: + kind: Service + name: docs-preview + weight: 100 + wildcardPolicy: None +status: {} diff --git a/helm/templates/docs-preview-build.yaml b/helm/templates/docs-preview-build.yaml new file mode 100644 index 0000000..25ee0cd --- /dev/null +++ b/helm/templates/docs-preview-build.yaml @@ -0,0 +1,30 @@ +apiVersion: build.openshift.io/v1 +kind: BuildConfig +metadata: + labels: + app: docs-preview + name: docs-preview +spec: + failedBuildsHistoryLimit: 2 + output: + to: + kind: ImageStreamTag + name: docs-preview:latest + postCommit: {} + resources: {} + runPolicy: Serial + source: + git: + uri: {{ .Values.git.source }} + type: Git + strategy: + sourceStrategy: + from: + kind: DockerImage + name: registry.fedoraproject.org/f33/python3 + type: Source + successfulBuildsHistoryLimit: 1 + triggers: + - type: ImageChange + - type: ConfigChange +status: {} diff --git a/helm/templates/docs-preview-deploy.yaml b/helm/templates/docs-preview-deploy.yaml new file mode 100644 index 0000000..10c3127 --- /dev/null +++ b/helm/templates/docs-preview-deploy.yaml @@ -0,0 +1,87 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + image.openshift.io/triggers: '[{"from":{"kind":"ImageStreamTag","name":"docs-preview:latest"},"fieldPath":"spec.template.spec.containers[?(@.name==\"docs-preview\")].image"}]' + labels: + app: docs-preview + name: docs-preview +spec: + progressDeadlineSeconds: 600 + replicas: {{ .Values.replicas }} + revisionHistoryLimit: 10 + selector: + matchLabels: + deployment: docs-preview + strategy: + type: Recreate + template: + metadata: + labels: + deployment: docs-preview + spec: + containers: + - image: bitnami/nginx:1.16-centos-7 + imagePullPolicy: IfNotPresent + name: web-server + ports: + - containerPort: 8080 + protocol: TCP + resources: + limits: + cpu: "1" + memory: 1G + requests: + cpu: 200m + memory: 200M + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /app + name: content-vol + - mountPath: /opt/bitnami/nginx/conf/server_blocks + name: nginx-conf + - env: + - name: BUILDSECRET + value: {{ .Values.secret }} + - name: BUILDROOT + value: /builds + - name: WORKPATH + value: /work + - name: REMOTEURL + value: {{ .Values.git.docs }} + image: ' ' # image-registry.openshift-image-registry.svc:5000/{{ .Release.Namespace }}/docs-preview:latest + imagePullPolicy: IfNotPresent + name: docs-preview + ports: + - containerPort: 8081 + protocol: TCP + resources: + limits: + cpu: "1" + memory: 1G + requests: + cpu: 200m + memory: 200M + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /builds + name: content-vol + - mountPath: /work + name: workpath + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - emptyDir: {} + name: content-vol + - emptyDir: {} + name: workpath + - configMap: + defaultMode: 420 + name: nginx-config + name: nginx-conf +status: {} diff --git a/helm/templates/docs-preview-hook-service.yaml b/helm/templates/docs-preview-hook-service.yaml new file mode 100644 index 0000000..071756a --- /dev/null +++ b/helm/templates/docs-preview-hook-service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: docs-preview-hook +spec: + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - port: 8081 + protocol: TCP + targetPort: 8081 + selector: + deployment: docs-preview + sessionAffinity: None + type: ClusterIP +status: + loadBalancer: {} diff --git a/helm/templates/docs-preview-is.yaml b/helm/templates/docs-preview-is.yaml new file mode 100644 index 0000000..f118e77 --- /dev/null +++ b/helm/templates/docs-preview-is.yaml @@ -0,0 +1,5 @@ +apiVersion: image.openshift.io/v1 +kind: ImageStream +metadata: + name: docs-preview +status: {} diff --git a/helm/templates/docs-preview-service.yaml b/helm/templates/docs-preview-service.yaml new file mode 100644 index 0000000..13ddd90 --- /dev/null +++ b/helm/templates/docs-preview-service.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: docs-preview + name: docs-preview +spec: + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - name: 8080-tcp + port: 8080 + protocol: TCP + targetPort: 8080 + selector: + deployment: docs-preview + sessionAffinity: None + type: ClusterIP +status: + loadBalancer: {} diff --git a/helm/templates/nginx-conf-configmap.yaml b/helm/templates/nginx-conf-configmap.yaml new file mode 100644 index 0000000..4446992 --- /dev/null +++ b/helm/templates/nginx-conf-configmap.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +data: + my_server_block.conf: | + server { + listen 8080; + location / { + root /app; + index index.html; + autoindex on; + } + #rewrite ^/(.*[^/])$ $scheme://$http_host/$1/ permanent; + port_in_redirect off; + } +kind: ConfigMap +metadata: + name: nginx-config diff --git a/helm/values.yaml b/helm/values.yaml new file mode 100644 index 0000000..17caa68 --- /dev/null +++ b/helm/values.yaml @@ -0,0 +1,8 @@ +git: + source: https://github.com/cscfi/docs-preview + docs: https://github.com/cscfi/csc-user-guide +secret: + +host: csc-guide-preview.rahtiapp.fi + +replicas: 1 diff --git a/requirements.txt b/requirements.txt index 86c0e39..e83ff3d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ # Additional packages for preview Flask==2.2.5 itsdangerous==2.1.2 -werkzeug==3.0.3 +werkzeug==3.0.6 # Packages for building the static pages babel==2.16.0 @@ -14,7 +14,7 @@ ghp-import==2.1.0 gitdb==4.0.11 GitPython==3.1.43 idna==3.7 -Jinja2==3.1.4 +Jinja2==3.1.5 Markdown==3.6 MarkupSafe==2.1.5 mergedeep==1.3.4 @@ -42,3 +42,4 @@ six==1.16.0 smmap==5.0.1 urllib3==2.2.2 watchdog==4.0.2 +