From a64e6e57d4635299ff0d5fdd243b36e41553143b Mon Sep 17 00:00:00 2001 From: jukov_mn Date: Wed, 20 May 2026 15:19:49 +0500 Subject: [PATCH] test --- Jenkinsfile | 63 ++++++++ docker/Dockerfile | 54 +++++++ docker/container-files/bootstrap/Pipfile | 12 ++ docker/container-files/bootstrap/app/cli.py | 30 ++++ .../bootstrap/app/mkdocs/common.py | 138 ++++++++++++++++++ docker/container-files/bootstrap/main.py | 4 + docker/container-files/bootstrap/setup.py | 15 ++ docker/container-files/root/.ssh/config | 2 + docker/default.conf | 23 +++ package.json | 5 + mkdocs/requirements.txt => requirements.txt | 0 11 files changed, 346 insertions(+) create mode 100644 Jenkinsfile create mode 100644 docker/Dockerfile create mode 100644 docker/container-files/bootstrap/Pipfile create mode 100644 docker/container-files/bootstrap/app/cli.py create mode 100644 docker/container-files/bootstrap/app/mkdocs/common.py create mode 100644 docker/container-files/bootstrap/main.py create mode 100644 docker/container-files/bootstrap/setup.py create mode 100644 docker/container-files/root/.ssh/config create mode 100644 docker/default.conf create mode 100644 package.json rename mkdocs/requirements.txt => requirements.txt (100%) diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..851aae4 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,63 @@ +node { + cleanWs() + checkout scm + + docker_tag = 'latest' + projectname ='app' + + packagejson = readJSON file: 'package.json' + docker_tag = packagejson['version'] + projectname = packagejson['name'] + + image_name = 'dhub.lex.lan:5001/doc/' + projectname; + image_doc = image_name + ':' + docker_tag; + image_doc_latest = image_name + ':latest'; +} +pipeline { + agent any + options { + timestamps() + buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '5') + ansiColor('xterm') + } + + stages { + stage('Check') { + steps { + echo 'Checking..' + + sh label: '', script: 'docker --version' + + //sh "printenv | sort" + } + } + stage('Docker build') { + steps { + echo 'Docker build....' + + sh label: '', script: 'docker build -f ./docker/Dockerfile --build-arg docker_registry=dhub.lex.lan:5000 -t ' + image_doc + ' .' + } + } + stage('Docker tag latest') { + steps { + sh label: 'tag image_doc latest', script: 'docker tag ' + image_doc + ' ' + image_doc_latest + } + } + stage('docker push'){ + steps { + script { + docker.withRegistry('http://dhub.lex.lan:5001/', '6173afa3-27b0-4357-8b97-9d1ee071784c') { + docker.image(image_doc).push() + docker.image(image_doc_latest).push() + } + } + } + } + stage('docker cleanup'){ + steps { + sh label: '', script: 'docker rmi ' + image_doc + sh label: '', script: 'docker rmi ' + image_doc_latest + } + } + } +} \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..039edac --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,54 @@ +FROM alpine:latest AS builder + +ENV MKDOCS_VERSION=1.1.0 \ + DOCS_DIRECTORY='/mkdocs' \ + LIVE_RELOAD_SUPPORT='false' \ + ADD_MODULES='false' \ + FAST_MODE='false' \ + PYTHONUNBUFFERED=1 \ + GIT_REPO='false' \ + GIT_BRANCH='master' \ + AUTO_UPDATE='false' \ + UPDATE_INTERVAL=15 + +RUN \ + apk add --update \ + ca-certificates \ + bash \ + git \ + openssh \ + python3 \ + python3-dev \ + py3-setuptools \ + py-pip \ + build-base + +ADD docker/container-files/ / + +RUN python -m venv /src/env +# Enable venv +ENV PATH="/src/env/bin:$PATH" + +ADD requirements.txt /src/ + +RUN \ + pip install --upgrade pip && \ + pip install --ignore-installed -r /src/requirements.txt && \ + cd /bootstrap && pip install -e /bootstrap && \ + rm -rf /tmp/* /var/tmp/* /var/cache/apk/* /var/cache/distfiles/* && \ + chmod 600 /root/.ssh/config + +CMD ["/usr/bin/bootstrap", "start"] + +FROM builder as makestatic +ADD docs /src/docs/ +#ADD overrides /src/overrides/ +ADD mkdocs.yml /src/ +ENV PATH="/src/env/bin:$PATH" + +RUN cd /src && mkdocs build + +FROM nginx +# RUN rm /etc/nginx/sites-enabled/default +COPY docker/default.conf /etc/nginx/conf.d/default.conf +COPY --from=makestatic /src/site /sites/app.lexema.ru/docs \ No newline at end of file diff --git a/docker/container-files/bootstrap/Pipfile b/docker/container-files/bootstrap/Pipfile new file mode 100644 index 0000000..d54965e --- /dev/null +++ b/docker/container-files/bootstrap/Pipfile @@ -0,0 +1,12 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] + +[packages] +click = "*" + +[requires] +python_version = "3.8" diff --git a/docker/container-files/bootstrap/app/cli.py b/docker/container-files/bootstrap/app/cli.py new file mode 100644 index 0000000..d14bf31 --- /dev/null +++ b/docker/container-files/bootstrap/app/cli.py @@ -0,0 +1,30 @@ +import click +from app.mkdocs import common + +"""CLI commands interface + + These are the primitive operation wrappers that the CLI + will expose and be available to invoke. + In order to do so, the comprehensive Click library is used to + create commands, subcommands, parameters, flags... + + .. _Click CLI library docs: + https://click.palletsprojects.com/en/7.x/#documentation +""" + + +@click.group(chain=True) +def cli() -> None: + """ + Bootstrap CLI + """ + + +@cli.command('start', help='Start Application') +def start(): + common.start() + + +@cli.command('update', help='Update documentation code from repository') +def update(): + common.update_repo() diff --git a/docker/container-files/bootstrap/app/mkdocs/common.py b/docker/container-files/bootstrap/app/mkdocs/common.py new file mode 100644 index 0000000..7ceb066 --- /dev/null +++ b/docker/container-files/bootstrap/app/mkdocs/common.py @@ -0,0 +1,138 @@ +import os +from termcolor import colored +import git +from datetime import datetime +from crontab import CronTab + +docks_dir = os.environ['DOCS_DIRECTORY'] +modules = os.environ['ADD_MODULES'] +repo = os.environ['GIT_REPO'] +git_branch = os.environ['GIT_BRANCH'] +auto_update = os.environ['AUTO_UPDATE'] +interval = int(os.environ['UPDATE_INTERVAL']) + + +def start(): + """ + Start mkdocs server + :return: + """ + if modules != 'false': + _install_modules(modules) + if repo != 'false': + _clone_repo(repo) + _check_previous_installation() + print('Starting MKDocs') + os.chdir(docks_dir) + if "DEV_ADDR" in os.environ: + _dev_addr = os.environ['DEV_ADDR'] + else: + _dev_addr = '0.0.0.0:8000' + os.system(f'mkdocs serve -a {_dev_addr} {_live_reload()} {_fast_mode()}') + + +def _install_modules(modules): + """ + Install Additional Modules + :param modules: str - List of modules to install + :return: + """ + print(colored(f'Installing python modules: {modules}', 'green')) + os.system(f'pip install -q {modules}') + print(colored(f'Modules installed.', 'green')) + + +def _check_previous_installation(): + """ + Check if previous installation present + Creates empty documentation if none detected + :return: + """ + if not os.path.exists(docks_dir + '/mkdocs.yml'): + print(colored( + f'No documentation found in ({docks_dir}). Creating new one.', 'yellow')) + if not os.path.exists(docks_dir): + os.mkdir(docks_dir) + print(colored(f'Starting fresh installation', 'green')) + os.system(f'mkdocs new {docks_dir}/') + else: + print( + colored(f'Detected previous installation in ({docks_dir}).', 'green')) + + +def _live_reload(): + """ + Live Reload + Auto Reload on file change + :return: + """ + if os.environ['LIVE_RELOAD_SUPPORT'] == 'false': + print(colored(f'LIVE RELOAD - [ DISABLED ]', 'red')) + reload = '--no-livereload' + else: + print(colored(f'LIVE RELOAD - [ ENABLED ]', 'green')) + reload = '' + return reload + + +def _fast_mode(): + """ + Fast Mode + Enables/Disables fast reload. + Enabled: build only files that got changed + Disabled: builds all files regardless of changes + :return: + """ + if os.environ['FAST_MODE'] == 'false': + print(colored(f'FAST_MODE - [ DISABLED ]', 'red')) + fast = '' + else: + print(colored(f'FAST_MODE - [ ENABLED ]', 'green')) + fast = '--dirtyreload' + return fast + + +def _set_auto_update(interval): + """ + Creates cron job for auto updating repository + :param interval: (every x minutes) + :return: + """ + os.system(f'crond') + cron = CronTab(user='root') + cron.remove_all() + job = cron.new(command='bootstrap update', comment='update') + job.minute.every(interval) + cron.write() + + +def _clone_repo(repo): + """ + Clone Documentation Code from git repository + :return: + """ + if not os.path.exists(docks_dir + '/mkdocs.yml'): + print(colored(f'Getting documentation from: {repo}', 'green')) + git.Repo.clone_from(repo, docks_dir, branch=git_branch) + + if auto_update == 'true': + print(colored(f'AUTO_UPDATE - [ ENABLED ]', 'green')) + print( + colored(f'UPDATE_INTERVAL set to every {interval} minute/s', 'green')) + _set_auto_update(interval) + + +def update_repo(): + """ + Fetching latest changes + :return: + """ + repo = git.Repo(docks_dir) + for remote in repo.remotes: + remote.fetch() + remote.pull() + headcommit = repo.head.commit + commit_date = datetime.fromtimestamp(headcommit.authored_date) + print(colored( + f'Pulled branch: {git_branch} \nCommit: {headcommit.hexsha} \nCommit Message: {headcommit.message}Date: {commit_date} \nAuthor: {headcommit.committer.name}', + 'green')) diff --git a/docker/container-files/bootstrap/main.py b/docker/container-files/bootstrap/main.py new file mode 100644 index 0000000..cab510f --- /dev/null +++ b/docker/container-files/bootstrap/main.py @@ -0,0 +1,4 @@ +from app.cli import cli + +if __name__ == '__main__': + cli() diff --git a/docker/container-files/bootstrap/setup.py b/docker/container-files/bootstrap/setup.py new file mode 100644 index 0000000..0ac2203 --- /dev/null +++ b/docker/container-files/bootstrap/setup.py @@ -0,0 +1,15 @@ +from setuptools import setup + +setup( + name='bootstrap', + version='1.0.0', + py_modules=['bootstrap'], + include_package_data=True, + install_requires=[ + 'click', 'termcolor', 'GitPython', 'python-crontab' + ], + entry_points=''' + [console_scripts] + bootstrap=app.cli:cli + ''', +) diff --git a/docker/container-files/root/.ssh/config b/docker/container-files/root/.ssh/config new file mode 100644 index 0000000..64779c2 --- /dev/null +++ b/docker/container-files/root/.ssh/config @@ -0,0 +1,2 @@ +Host * + StrictHostKeyChecking no \ No newline at end of file diff --git a/docker/default.conf b/docker/default.conf new file mode 100644 index 0000000..2395804 --- /dev/null +++ b/docker/default.conf @@ -0,0 +1,23 @@ + +server { + listen 80; + + # location / { + root /sites/app.lexema.ru/docs; + # } + #expires $expires; + + client_max_body_size 500M; + + gzip on; + gzip_comp_level 4; + gzip_types text/html text/plain text/css application/javascript; + + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-NginX-Proxy true; + +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..da479de --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "name": "lexema8-doc", + "version": "0.0.10", + "description": "lexema 8.4 doc" +} diff --git a/mkdocs/requirements.txt b/requirements.txt similarity index 100% rename from mkdocs/requirements.txt rename to requirements.txt