How to automatically deploy from GitHub to Hosting

Как автоматизировать deploy с GitHub на Хостинг?

Для автоматической загрузки из репозитория GitHub на ваш хостинг существует множество различных вариантов, как например вот этот взятый из Q&A Habra:

Написать bash скрипт который выполнит всё это, а для автоматизации запихнуть его в cron.
sshpass -pPASSWORD ssh -T git@github.com cd example.com/www;git checkout master;git pull
Естественно для такого выполнения нужно сначала установить sshpass apt install sshpass Хотя можно и без него, но надо будет пароль вводить
ssh -T git@github.com cd example.com/www;git checkout master;git pull

Оригинал тут: https://qna.habr.com/q/447805

Но кто из нас не любит изобретать свой велосипед? 🙂
Я тоже люблю и поэтому вот мой:

Мой велосипед

Логика заключается в том чтобы, при коммите, GitHub выполнял actions с помощью которого подключался к виртуальной машине по ssh на хостинг где расположен сайт и там выполнял команду git_pull() для загрузки последних изменений из репозитория. Я создал отдельный каталог (следует понимать что это не каталог публикации который виден из Интернета) где разместил чистый репозиторий, а затем синхронизировал с удаленным.

После мы выполняем скрипт ниже, который скопирует в папку публикации (как правило public_html) все файлы и папки кроме тех что будут переданы третьим аргументом в функцию copy_content(..., ..., ['укажите тут', 'через запятую', 'файлы или папки', 'которые нельзя копировать', 'например', '.git'])

Подготовка

Скрипт переноса файлов/папок из директории с git репозиторием

#!/usr/bin/env python
# move files from repo to public_html
import os
import shutil
print("Starting move files...")
source_path = os.path.normcase(os.path.abspath(os.getcwd() + "/path/repo/projectname.git/"))
destination_path = os.path.normcase(os.path.abspath(os.getcwd() + "/path/public_html/"))
def delete_directory_and_files(path):
    for filename in os.listdir(path):
        path_name = os.path.join(path, filename)
        try:
            if os.path.isfile(path_name) or os.path.islink(path_name):
                os.unlink(path_name)
            elif os.path.isdir(path_name):
                shutil.rmtree(path_name)
        except Exception as e:
            print('Failed to delete %s. Reason: %s' % (filename, e))
def copy_content(src, dst, ignore_src=[]):
    delete_directory_and_files(dst)
    for filename in os.listdir(src):
        if filename not in ignore_src:
            path_src = os.path.join(src, filename)
            path_dst = os.path.join(dst, filename)
            try:
                if os.path.isfile(path_src) or os.path.islink(path_src):
                    shutil.copy2(path_src, path_dst)
                    print("copy file: {}".format(filename))
                elif os.path.isdir(path_src):
                    shutil.copytree(path_src, path_dst)
                    print("copy folder: {}".format(filename))
            except Exception as e:
                print('Error: {}'.format(e))
copy_content(source_path, destination_path, ['.git', '.github'])
print("Move completed!")

Продолжение следует…