Loading .deploy_code_to_server.yml +66 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,72 @@ changes: - "**/*.scss" .deploy_folder_to_server: extends: .before_deploy_code variables: RSYNC_PARAMS: '--delete --dry-run' USE_RSYNC_FILTER: 'false' # DEPLOY_LOCAL_DIR: source directory relative to $CI_PROJECT_DIR (required, non-empty) # DEPLOY_REMOTE_DIR: destination subdirectory under $DEPLOY_HOST_PATH (required; # use '' for flat/doc-root deploy, or a path for subdirectory deploy) script: - | if [[ -z "${DEPLOY_LOCAL_DIR}" ]]; then echo "ERROR: DEPLOY_LOCAL_DIR must be set to a non-empty string" >&2 exit 1 fi if [[ ! -v DEPLOY_REMOTE_DIR ]]; then echo "ERROR: DEPLOY_REMOTE_DIR must be explicitly set ('' for flat deploy, path for subdirectory)" >&2 exit 1 fi - chmod $PROJECT_ROOT_PERMS $CI_PROJECT_DIR - | if [[ "$USE_RSYNC_FILTER" == 'true' ]]; then which curl || (apt-get update -y && apt-get install curl -y) curl -O https://gitlab.cetera.ru/boilerplate/ci/raw/master/rsync-filter-std if [ -e rsync-filter ]; then export PROJECT_FILTER="rsync-filter" else curl -O "https://gitlab.cetera.ru/boilerplate/ci/raw/master/rsync-filter-${PROJECT_CMS_TYPE}" export PROJECT_FILTER="rsync-filter-${PROJECT_CMS_TYPE}" fi echo "PROJECT_FILTER set to $PROJECT_FILTER" sed -i 's|/www/|/|g' "$PROJECT_FILTER" fi - | if [[ -n "$DEPLOY_REMOTE_DIR" ]]; then remote_path="$DEPLOY_HOST_PATH/$DEPLOY_REMOTE_DIR/" else remote_path="$DEPLOY_HOST_PATH/" fi if [[ "$USE_RSYNC_FILTER" == 'true' ]]; then rsync $RSYNC_ADMIN_PARAMS -e "ssh $SSH_OPTS" \ --filter="merge rsync-filter-std" --filter="merge $PROJECT_FILTER" \ $RSYNC_PARAMS $CI_PROJECT_DIR/$DEPLOY_LOCAL_DIR/ $remote_path else rsync $RSYNC_ADMIN_PARAMS -e "ssh $SSH_OPTS" \ $RSYNC_PARAMS $CI_PROJECT_DIR/$DEPLOY_LOCAL_DIR/ $remote_path fi dependencies: - setup_environment_vars rules: - if: $CI_COMMIT_REF_PROTECTED == 'true' .deploy_doc_root_to_server_with_delete: extends: .deploy_folder_to_server variables: DEPLOY_LOCAL_DIR: www DEPLOY_REMOTE_DIR: '' USE_RSYNC_FILTER: 'true' RSYNC_PARAMS: '--delete --dry-run' rules: - if: $CI_COMMIT_REF_NAME == 'beta' changes: - www/**/* - .gitlab-ci.yml deploy_autotests_to_server: extends: .before_deploy_code script: Loading tests/integration/extract_scripts.py +47 −6 Original line number Diff line number Diff line Loading @@ -5,8 +5,11 @@ Writes shell scripts to OUTPUT_DIR (default /tmp/generated): set_path_vars.sh — from before_script.yml anchor deploy_code_to_server.sh — from .deploy_code_to_server script: deploy_code_to_server_with_delete.sh — from .deploy_code_to_server_with_delete script: deploy_folder_to_server.sh — from .deploy_folder_to_server script: deploy_doc_root_to_server_with_delete.sh — from .deploy_doc_root_to_server_with_delete (extends .deploy_folder_to_server) deploy_js_files_to_server.sh — from .deploy_js_files_to_server script: upload_composer_files.sh — from .deploy_composer_files_to_server.yml anchor deploy_js_files_to_server.sh — from .deploy_code_to_server.yml .deploy_js_files_to_server script: upload_cms_files.sh — from .deploy_composer_files_to_server.yml anchor """ import os import sys Loading @@ -26,6 +29,42 @@ def join_script(steps): return '\n'.join(step.rstrip('\n') for step in steps) + '\n' def resolve_script(jobs, job_name): """Return the script list for job_name, following extends: if needed.""" job = jobs[job_name] if 'script' in job: return job['script'] extends = job.get('extends') if extends: if isinstance(extends, list): extends = extends[0] return resolve_script(jobs, extends) return [] def make_shell_script(jobs, job_name): """Build a shell script for job_name. If the job delegates its script to a parent via extends:, prepend the job's own variables as shell defaults (${VAR:-value}) so that the environment can still override them — matching how GitLab CI merges variables at runtime. """ job = jobs[job_name] script = resolve_script(jobs, job_name) if 'script' not in job: preamble = [] for k, v in job.get('variables', {}).items(): if v is None or v == '': preamble.append(f'export {k}="${{{k}-}}"') else: preamble.append(f'export {k}="${{{k}:-{v}}}"') script = preamble + list(script) return join_script(script) def main(output_dir): os.makedirs(output_dir, exist_ok=True) Loading @@ -43,11 +82,13 @@ def main(output_dir): for job, name in [ ('.deploy_code_to_server', 'deploy_code_to_server.sh'), ('.deploy_code_to_server_with_delete', 'deploy_code_to_server_with_delete.sh'), ('.deploy_folder_to_server', 'deploy_folder_to_server.sh'), ('.deploy_doc_root_to_server_with_delete', 'deploy_doc_root_to_server_with_delete.sh'), ('.deploy_js_files_to_server', 'deploy_js_files_to_server.sh'), ]: path = os.path.join(output_dir, name) with open(path, 'w') as f: f.write(join_script(deploy[job]['script'])) f.write(make_shell_script(deploy, job)) print(f'Written {path}') with open(os.path.join(REPO_ROOT, '.deploy_composer_files_to_server.yml')) as f: Loading tests/integration/fixtures/project/echo-server/app.js 0 → 100644 +1 −0 Original line number Diff line number Diff line // echo server app tests/integration/fixtures/recipient-seed-flat/.htaccess 0 → 100644 +1 −0 Original line number Diff line number Diff line # htaccess — preserved by rsync-filter-std protect rule tests/integration/fixtures/recipient-seed-flat/bitrix/dbconn.php 0 → 100644 +1 −0 Original line number Diff line number Diff line <?php // bitrix db config Loading
.deploy_code_to_server.yml +66 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,72 @@ changes: - "**/*.scss" .deploy_folder_to_server: extends: .before_deploy_code variables: RSYNC_PARAMS: '--delete --dry-run' USE_RSYNC_FILTER: 'false' # DEPLOY_LOCAL_DIR: source directory relative to $CI_PROJECT_DIR (required, non-empty) # DEPLOY_REMOTE_DIR: destination subdirectory under $DEPLOY_HOST_PATH (required; # use '' for flat/doc-root deploy, or a path for subdirectory deploy) script: - | if [[ -z "${DEPLOY_LOCAL_DIR}" ]]; then echo "ERROR: DEPLOY_LOCAL_DIR must be set to a non-empty string" >&2 exit 1 fi if [[ ! -v DEPLOY_REMOTE_DIR ]]; then echo "ERROR: DEPLOY_REMOTE_DIR must be explicitly set ('' for flat deploy, path for subdirectory)" >&2 exit 1 fi - chmod $PROJECT_ROOT_PERMS $CI_PROJECT_DIR - | if [[ "$USE_RSYNC_FILTER" == 'true' ]]; then which curl || (apt-get update -y && apt-get install curl -y) curl -O https://gitlab.cetera.ru/boilerplate/ci/raw/master/rsync-filter-std if [ -e rsync-filter ]; then export PROJECT_FILTER="rsync-filter" else curl -O "https://gitlab.cetera.ru/boilerplate/ci/raw/master/rsync-filter-${PROJECT_CMS_TYPE}" export PROJECT_FILTER="rsync-filter-${PROJECT_CMS_TYPE}" fi echo "PROJECT_FILTER set to $PROJECT_FILTER" sed -i 's|/www/|/|g' "$PROJECT_FILTER" fi - | if [[ -n "$DEPLOY_REMOTE_DIR" ]]; then remote_path="$DEPLOY_HOST_PATH/$DEPLOY_REMOTE_DIR/" else remote_path="$DEPLOY_HOST_PATH/" fi if [[ "$USE_RSYNC_FILTER" == 'true' ]]; then rsync $RSYNC_ADMIN_PARAMS -e "ssh $SSH_OPTS" \ --filter="merge rsync-filter-std" --filter="merge $PROJECT_FILTER" \ $RSYNC_PARAMS $CI_PROJECT_DIR/$DEPLOY_LOCAL_DIR/ $remote_path else rsync $RSYNC_ADMIN_PARAMS -e "ssh $SSH_OPTS" \ $RSYNC_PARAMS $CI_PROJECT_DIR/$DEPLOY_LOCAL_DIR/ $remote_path fi dependencies: - setup_environment_vars rules: - if: $CI_COMMIT_REF_PROTECTED == 'true' .deploy_doc_root_to_server_with_delete: extends: .deploy_folder_to_server variables: DEPLOY_LOCAL_DIR: www DEPLOY_REMOTE_DIR: '' USE_RSYNC_FILTER: 'true' RSYNC_PARAMS: '--delete --dry-run' rules: - if: $CI_COMMIT_REF_NAME == 'beta' changes: - www/**/* - .gitlab-ci.yml deploy_autotests_to_server: extends: .before_deploy_code script: Loading
tests/integration/extract_scripts.py +47 −6 Original line number Diff line number Diff line Loading @@ -5,8 +5,11 @@ Writes shell scripts to OUTPUT_DIR (default /tmp/generated): set_path_vars.sh — from before_script.yml anchor deploy_code_to_server.sh — from .deploy_code_to_server script: deploy_code_to_server_with_delete.sh — from .deploy_code_to_server_with_delete script: deploy_folder_to_server.sh — from .deploy_folder_to_server script: deploy_doc_root_to_server_with_delete.sh — from .deploy_doc_root_to_server_with_delete (extends .deploy_folder_to_server) deploy_js_files_to_server.sh — from .deploy_js_files_to_server script: upload_composer_files.sh — from .deploy_composer_files_to_server.yml anchor deploy_js_files_to_server.sh — from .deploy_code_to_server.yml .deploy_js_files_to_server script: upload_cms_files.sh — from .deploy_composer_files_to_server.yml anchor """ import os import sys Loading @@ -26,6 +29,42 @@ def join_script(steps): return '\n'.join(step.rstrip('\n') for step in steps) + '\n' def resolve_script(jobs, job_name): """Return the script list for job_name, following extends: if needed.""" job = jobs[job_name] if 'script' in job: return job['script'] extends = job.get('extends') if extends: if isinstance(extends, list): extends = extends[0] return resolve_script(jobs, extends) return [] def make_shell_script(jobs, job_name): """Build a shell script for job_name. If the job delegates its script to a parent via extends:, prepend the job's own variables as shell defaults (${VAR:-value}) so that the environment can still override them — matching how GitLab CI merges variables at runtime. """ job = jobs[job_name] script = resolve_script(jobs, job_name) if 'script' not in job: preamble = [] for k, v in job.get('variables', {}).items(): if v is None or v == '': preamble.append(f'export {k}="${{{k}-}}"') else: preamble.append(f'export {k}="${{{k}:-{v}}}"') script = preamble + list(script) return join_script(script) def main(output_dir): os.makedirs(output_dir, exist_ok=True) Loading @@ -43,11 +82,13 @@ def main(output_dir): for job, name in [ ('.deploy_code_to_server', 'deploy_code_to_server.sh'), ('.deploy_code_to_server_with_delete', 'deploy_code_to_server_with_delete.sh'), ('.deploy_folder_to_server', 'deploy_folder_to_server.sh'), ('.deploy_doc_root_to_server_with_delete', 'deploy_doc_root_to_server_with_delete.sh'), ('.deploy_js_files_to_server', 'deploy_js_files_to_server.sh'), ]: path = os.path.join(output_dir, name) with open(path, 'w') as f: f.write(join_script(deploy[job]['script'])) f.write(make_shell_script(deploy, job)) print(f'Written {path}') with open(os.path.join(REPO_ROOT, '.deploy_composer_files_to_server.yml')) as f: Loading
tests/integration/fixtures/project/echo-server/app.js 0 → 100644 +1 −0 Original line number Diff line number Diff line // echo server app
tests/integration/fixtures/recipient-seed-flat/.htaccess 0 → 100644 +1 −0 Original line number Diff line number Diff line # htaccess — preserved by rsync-filter-std protect rule
tests/integration/fixtures/recipient-seed-flat/bitrix/dbconn.php 0 → 100644 +1 −0 Original line number Diff line number Diff line <?php // bitrix db config