13 января 2023 г.

Деплой ассетов CI через sftp

Синопсис

На заключительном этапе подготовки верстки для сайта при запуске npm run build мой вебпак готовит папку dist следующим образом:

- assets
 - css
  • app.9a8dva.css
 - js
  • app.9a8dva.js

Затем я подключаюсь по ftp, закидываю в соотвествующие папки эти файлы. В админке MODx в расширении ClientConfig обновляю поле хэша, в данном случае "9a8dva". (в чанках ассеты используют настройку 22cee16c7130d01c668b и это решает проблему вредного кэша)

Все это занимает может минуту, но.

При переносе верстки на движок постоянно вылезают какие-то косячки. И процесс становится ощутимо болезненным по времени. Поэтому я решил его немного автоматизировать.

Нам понадобится:

Качаем, пачаны!

Поскольку у меня конфиг вебпака разбит на 2 части, для разработки и билда, то в последний под названием webpack.build.conf.js импортируем и используем плагины:

	
	const WebpackShellPlugin = require('webpack-shell-plugin')
	const { CleanWebpackPlugin } = require('clean-webpack-plugin');

	plugins: [
    new CleanWebpackPlugin(),
    new WebpackShellPlugin({
      onBuildStart:['echo • Start building awesome'], 
      onBuildEnd:['bash deploy/start.sh']})]
	})

Итак, один плагин чистит папку билд перед билдом. Второй запускает скрипт bash после того как все сбилдилось.

Создадим папку deploy в корне проекта с такой структурой:

	- psftp.exe
	- s.scr
	- start.sh

Где s.scr - файл с командами для psftp. Содержимое файлов:

start.sh


	#!/usr/bin/env bash
	p="/mnt/host/c/Users/user/Desktop/WEBPACK PROJECTS/site.local/deploy/"
	s="C:\Users\user\Desktop\WEBPACK PROJECTS\site.local\deploy\\"

	"${p}psftp.exe" -pw password user@by143.net -b "${s}s.scr" -be

	c="/mnt/host/c/Program Files/Git/mingw64/bin/curl.exe"

	"${c}" -k https://dev.site.by/assets/php/assets_hash_update.php

	

В переменные p,s,c я засунул пути. Обратите внимание, что у p есть некий префикс "/mnt/host/", думаю это из-за того, что внутри вэбпака код выполняется. При запуске этого же кода через обычную консоль, путь без этой приставки.

В переменной s путь в "виндовс стиле" с бэкслешем в конце.

По итогу мы запускаем утилиту psftp.exe, передаем ей пароль, пользователя и хост. -b говорит нам использовать файл с командами, а -be велит игнорировать ошибки, если что.

В переменной «с» путь к curl. Появляется после установки утилиты гита. И вебпак не может прочесть глобальную переменную curl во время процесса билда, поэтому мы указываем ту же приставку "/mnt/host/"

В последней строке мы дергаем php скрипт, который прочитает файлы в директории css, вытащит оттуда хэш и обновит поле hash в clientConfig-e

s.scr
	cd /home/user/www/dev.site.by/assets/
	del css/*
	del js/*
	put -r "C:\Users\user\Desktop\WEBPACK PROJECTS\site.local\dist\assets\css"
	put -r "C:\Users\user\Desktop\WEBPACK PROJECTS\site.local\dist\assets\js"
	exit
Сначала мы переходим в папку ассетов сайта, удаляем их содержимое, затем копируем свежесобранные файлы командой put assets_hash_update.php
	

	define('MODX_API_MODE', true);
	require '../../index.php';


	$modx->getService('error','error.modError');
	$modx->setLogLevel(modX::LOG_LEVEL_INFO);
	$modx->setLogTarget(XPDO_CLI_MODE ? 'ECHO' : 'HTML');


	$path = $modx->getOption('core_path') . 'components/clientconfig/processors/';
	$props = array( 'processors_path' => $path);
	$dir = $_SERVER["DOCUMENT_ROOT"]."/assets/css/";


	if (is_dir($dir)){
	  if ($dh = opendir($dir)){
	    while (($file = readdir($dh)) !== false){
	        if($file !== "." && $file !== ".."){
	           $hash = explode(".",$file)[1];
	           
	           if(strlen($hash)){
	               $_POST = array('values' => '{"hash":"'.$hash.'"}' );
	               $modx->runProcessor('mgr/settings/save', $_POST, $props);
	               echo 'Hash '.$hash.' is applied';
	           } else {
	               echo 'Can not update hash';
	           }
	        }
	      
	    }
	    closedir($dh);
	  }
	}


На сервере мы будем использовать MODx API, чтобы ручками не подключаться к базе данных. Итак, еще раз - мы читаем файл в каталоге css, точнее бежим по всем файлам циклом. Берем попавшийся файл, бьем его имя по точкам, и первым элементом массива получаем искомую строку. В переменной с обязательным странным названием $_POST лежит строка типа json, где "hash" название поля в админке в дополнении ClientConfig, которое мы и будем обновлять выцепленной выше строкой, лежащей в переменной $hash.

Заключение

Собственно, все. Если у вас не будут выпадать сетевые ошибки, то каждый npm run build будет обновлять файлы и поле конфигурации в админки. Поздравляем! Вы великолепны!