Всем привет!
Пока сессия только начинается, а зачетные недели в самом разгаре я немного раскидался и хочу поделиться с Вами тем, как я выстроил процесс написания курсача. Возможно, такой формат больше подошел бы для написания диплома так как объем курсача все таки не настолько большой, чтобы так делать, однако совсем недавно я делал довольно объемную лабу по одному предмету и сыт по горло версткой формул в ворде.
Курсач я решил писать на латехе. Я не буду описывать то, как я это делаю. Латех - очень крутая штука и всю его крутость, думаю, не описать в одной статье. Может быть когда нибудь я даже это сделаю, но сегодня я хочу рассказать больше о процессе работы над курсачом.
Для тех, кто не в курсе: LaTeX - язык математической верстки, который можно компилировать в PDF файлы. Тыц
В отличие от файлов doc/docx .tex файлы - это код, а не нечитаймый xml или вообще бинарник, поэтому при разработке документов на латехе можно очень легко контролировать версии и даже делать это в команде благодаря системам контроля версий, например, git. И это несомненный плюс, так как позволяет отказаться от чего-то такого:
Окей, git это круто, но этого недостаточно для полного погружения, идем дальше. Курсач я пишу в VS Code и для этой ide есть просто шикарное расширение для работы с latex
Бам - https://marketplace.visualstudio.com/items?itemName=James-Yu.latex-workshop
Там есть поддержка разных компиляторов, очень гибкая настройка, хот-релоад при сохранении, просмотр pdf прямо в ide и много чего еще и это очень круто, советую. Также рекомендую поставить спеллчекер типа
https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker-russian
потому что все мы люди и все ошибаемся.
Так, ну со средой разобрались, использовать будем гит, выгружать будем на гитхаб, все как обычно. Но чего-то все равно не хватает. Хм... Точно! Нам нужен CI/CD.
Что есть CI/CD?
Вкратце, это такой подход к разработке, при котором автоматизируются такие процессы как тестирование, сборка и деплой продукта, позволяя очень быстро выявлять потенциальные проблемы и решать интеграционные проблемы.
Это очень удобно при разработке приложений, но для разработки документов на latex это не менее удобно.
Мы этим и займемся, а так как развернулись на гитхабе, будем использовать Github Actions.
Начинаем!
Для начала, нужно на вкладке Actions создать файлик с указаниями чо делат, этот файлик будет храниться в нашей репе в папке .github/workflows
%lang(yaml)% name: LaTeX ci/cd on: push: branches: [ master ] pull_request: branches: [ master ]
Мы говорим, что хотим запускать воркфлоу когда произошел пуш или пул влился пул реквест в master (#BLM ëпта) ветку нашей репы. Хорошо, а что делать?
%lang(yaml)% jobs: build_master: runs-on: ubuntu-latest
Назовем джобу build_master, потому что она билдит мастер (вау) и прикажем запускаться на ubuntu-latest
Дальше идут шаги нашего воркфлоу и их довольно много для latex документа
%lang(yaml)% steps: - name: Set up Git repository uses: actions/checkout@v2 - name: Compile LaTeX document uses: dante-ev/latex-action@master with: root_file: main.tex - name: Find latest version uses: oprypin/find-latest-tag@v1 id: latest_version with: repository: yungvldai/coursach releases-only: true
Сначала мы берем наш репозиторий, потом с помощью экшона dante-ev/latex-action компилируем наш tex в PDF, устанавливая main.tex как точку входа. Тут можно пользоваться еще экшоном xu-cheng/latex-action, но с ним с eskdtext были какие-то проблемы.
Затем ищем версию последнего тега, под которым выходил релиз, она пригодится нам позже.
%lang(yaml)% - name: Generate new version id: new_version uses: christian-draeger/increment-semantic-version@1.0.2 with: current-version: ${{ steps.latest_version.outputs.tag }} version-fragment: 'feature' - name: Declare some variables shell: bash id: some_vars run: | echo "##[set-output name=release_name;]$(date +"%d %b %Y at %H:%M")"
Вот нам и пригодилась версия, поднимается ее feature (минорную) часть на 1 с помощью экшона christian-draeger/increment-semantic-version, я использую semver. Что это такое?
Я решил, что мажорную версию буду поднимать в каких нибудь супер случаях (пока не придумал каких), а версии-патчи мне по сути не нужны, но они нужны для того, чтобы этот экшон работал, потому что он не может распознать semver в 1.0
Следует отметить, что первый релиз придется сделать ручками, чтобы экшону было что поднимать, иначе он поднимет панику, а кому это надо.
Далее нам надо прогнать одну команду, чтобы как-то назвать релиз, я решил называть их так:
Release <date> at <time>
GNU date с вернет что то типа 22 Dec 2020 at 14:45 при указании такого формата: +"%d %b %Y at %H:%M", это то, что нужно. Мы помещаем значение в переменную release_name вывода шага some_vars. Потом мы это используем.
%lang(yaml)% - name: Create Release id: create_release uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ steps.new_version.outputs.next-version }} release_name: Release ${{ steps.some_vars.outputs.release_name }} draft: false prerelease: false - name: Upload Release Asset id: upload-release-asset uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: ./main.pdf asset_name: coursach.pdf asset_content_type: application/pdf
Теперь мы создаем новый релиз и выгружаем туда наш скомпилированный PDF, который мы получили на шаге 2 (Compile LaTeX document) с помощью экшонов actions/create-release и actions/upload-release-asset. Мы забираем имя для релиза вот так:
steps.some_vars.outputs.release_name
Это означает что то типа: возьми имя для релиза из поля release_name вывода шага с id=some_vars. Смотрите выше как мы его генерируем.
После этих шагов в вкладке Releases нашего репозитория мы видим:
Единственная проблема - не нашел как подогнать часовой пояс. Сейчас время указывается в GMT+0, то есть время для меня отличается на 3 часа (так как я нахожусь в Петербурге). Ну да пофиг)))
%lang(yaml)% - name: Send e-mail uses: dawidd6/action-send-mail@v2 with: server_address: smtp.gmail.com server_port: 465 username: ${{ secrets.MAIL_USERNAME }} password: ${{ secrets.MAIL_PASSWORD }} subject: New coursach release body: "New release! - <a href='https://github.com/yungvldai/coursach/releases/latest/download/coursach.pdf'>Download now</a>" to: ${{ secrets.MAILING_LIST }} from: Deploy Bot content_type: text/html
Наконец, мы по электронной почте (с помощью dawidd6/action-send-mail) отправляем ссылку на загрузку новейшей версии PDF нашего курсача нашему научнику, а точнее всем, кто указан в secrets.MAILING_LIST (сделано для того, чтобы не светить нашей почтой, а также, чтобы для добавления почты не приходилось менять код). Для этого берется логин и пароль от реально существующей почты, которые я также передаю в secrets. О том как настроить secrets можно почитать тут:
https://docs.github.com/en/free-pro-team@latest/actions/reference/encrypted-secrets
Для теста я указал в MAILING_LIST и себя и каждый раз мне приходит письмо типа:
Ссылка из письма ведет на загрузку документа курсовой работы (точнее ее последнюю версию).
Зачем мне все это?
Это очень удобно. Я могу спокойно писать курсач, вести разработку в разных ветках, править что либо. При этом сохраняется история его написания. Самое крутое то, что как только я посчитаю, что можно показать текущее состояние руководителю, я просто волью ветку в master или сделаю пуш в него и все. Все сделается само. Само соберется, зарелизится и отправится на почту, которую я укажу, а я смогу спокойно идти пить чай и ждать отзыв от научника.
При этом никакой поддержки не требуется, я просто один раз написал конфиг для воркфлоу и все, можно забыть и спокойно писать курсач как будто я делаю это без всего этого.
Самое пугающее здесь - LaTeX, так как нужно уметь с ним работать, но и тут я Вас успокою, потому что понимание приходит спустя ~2 дня работы с ним. Повторюсь, возможно, не очень хороший выбор для курсовых работ и лабораторых, но для диплома (тех. специальности) самое оно.
Приложу, наконец, Вашу любимую кнопку:
Спасибо за внимание и пользуйтесь, оно того стоит.