Особенности национального Workflow: Секреты, кэш и артефакты в Github Actions

01.04.24

Интеграция - WEB-интеграция

Продолжаем знакомиться с инструментарием Github Actions. Рассмотрим сегодня методы хранения и использования секретных данных, связь работ между собой, а также передачу информации между работами

Если вы еще не знакомы с Github Actions, то начать лучше с первой статьи по теме:
Особенности национального Workflow: Github Actions и OneScript
Иначе многое может быть непонятно

 

В прошлый раз мы рассмотрели, что такое Github Actions и создали самый простой Workflow, который устанавливал OneScript и, с его помощью, выводил в консоль "Привет мир" - он состоял из одной работы и всего нескольких шагов. Это, разумеется, не предел - сейчас мы разберем, как сделать из одиночных работ полноценный многошаговый процесс, передавать между этими процессами информацию, а по итогу получить некоторый завершенный результат


Процесс тестирования OneScript версии Открытого пакета интеграций, например
 

Вернемся к нашему yml-файлу из прошлой статьи:
 

name: Test
on:
  workflow_dispatch:
jobs:
  RunOneScript:
    runs-on: ubuntu-latest  
    steps:

      - uses: actions/checkout@v3
      - uses: otymko/setup-onescript@v1.4
        with:
          version: 1.9.0 
          
      - name: Запускаем OneScript
        run: oscript ./workflow.os

 

Как мы помним, тут есть одна работа - RunOneScript, которая состоит из 3-х простых шагов

  1. Неименованного шага использования стандартного действия для доступа к репозиторию (checkout)
  2. Неименованного шага использования действия от otymko для установки OneScript
  3. Именованного шага запуска скрипта из файла workflow.os, который лежит у нас в репозитории

Пришло время добавить сюда второе действие. Для этого на том же уровне табуляции, (табуляция в yml крайне важна) что и RunOneScript, необходимо ввести название новой работы и заполнить её содержимое 

 

name: Test
on:
  workflow_dispatch:
jobs:
  RunOneScript:
    runs-on: ubuntu-latest  
    steps:

      - uses: actions/checkout@v3
      - uses: otymko/setup-onescript@v1.4
        with:
          version: 1.9.0 
          
      - name: Запускаем OneScript
        run: oscript ./workflow.os

  MySecondJob:
    runs-on: ubuntu-latest  
    steps:
      - name: Шаг из второго действия
        run: echo "Это второе действие"

 

Запустим и взглянем на схему выполнения

 

Работы объединены в одну группу. Это означает, что каждая из них выполняется параллельно - независимо от степени выполнения другой.

Такой вариант имеет право на жизнь, однако куда чаще различные работы необходимо выполнять не параллельно, а друг за другом - последовательно. Для этого в GA существует блок needs

needs принимает массив работ, завершение которых необходимо для запуск текущей. Добавим в работу MySecondJob подобную зависимость от RunOneScript

 

name: Test
on:
  workflow_dispatch:
jobs:
  RunOneScript:
    runs-on: ubuntu-latest  
    steps:

      - uses: actions/checkout@v3
      - uses: otymko/setup-onescript@v1.4
        with:
          version: 1.9.0 
          
      - name: Запускаем OneScript
        run: oscript ./workflow.os

  MySecondJob:
    runs-on: ubuntu-latest  
    needs: ["RunOneScript"] # При зависимости от одной работы допустимо указание и без квадратных скобок
    steps:
      - name: Шаг из второго действия
        run: echo "Это второе действие"


Теперь наша схема выглядит следующим образом

 

Выполнение работы MySecondJob начнется только после успешного выполнения RunOneScript. Однако, помимо указания порядка запуска работ, мы можем указать дополнительные условия, выполнение которых будет регламентировать, запуститься ли вообще следующая работа или нет

Делается это при помощи оператора if. Он может принимать любые переменные среды и сравнивать их с указанными значениями - как условие "если" в любых других языках программирования. Отдельного внимания (ввиду наиболее частого использования) тут заслуживают специальные, служебные переменные, отвечающие за статус выполнения предыдущей работы. К ним относятся:

  • ${{ always() }} - несмотря ни на что
  • ${{ cancelled() }} - если workflow был остановлен вручную
  • ${{ failure() }} - если предыдущая работа была завершена с ошибкой
  • ${{ success() }} - если предыдущая работа была завершена успешно 

С полной документацией по условиям можно ознакомиться тут, отметим лишь, что:

  1. if можно применять не только к работам, но и к шагам. По умолчанию, если какой-либо шаг завершается с ошибкой, то выполнение работы не продолжается. Избежать этого можно подобным образом:
    ...
    
    - name: Выполнить Шаг 1
       if: ${{ cancelled() }} == false
       run: echo "Шаг 1"
    - name: Выполнить Шаг 2
       if: ${{ cancelled() }} == false
       run: echo "Шаг 2"
    
    ...

    Вне зависимости от результата выполнения Шага 1, Шаг 2 начнет свое выполнение следом
     

  2. Важно различать always() и !cancelled() (cancelled() = false). В отличии от !cancelled(), allways() продолжит свое выполнение, даже если вы попытаетесь прервать рабочий процесс вручную

 

Подправим наш yml файл - добавим условие ${{ cancelled() }} == false второму шагу, а в первом намеренно вызовем ошибку

 

name: Test
on:
  workflow_dispatch:
jobs:
  RunOneScript:
    runs-on: ubuntu-latest  
    steps:

      - uses: actions/checkout@v3
      - uses: otymko/setup-onescript@v1.4
        with:
          version: 1.9.0 
          
      - name: Запускаем OneScript
        run: oscript ./workflow.os

      - name: Вызываем ошибку
        run: |
          echo Ошибка!
          exit 5

  MySecondJob:
    runs-on: ubuntu-latest  
    needs: ["RunOneScript"] 
    if: ${{ cancelled() }} == false
    steps:
      - name: Шаг из второго действия
        run: echo "Это второе действие"

 

Теперь запустим

 

Вторая работа выполнилась, несмотря на ошибку в первой, как мы и ожидали. Теперь, пожалуй, перейдем к чему-нибудь более близком реальной жизни

 

Сереты и кэш

 

Одной из важных задач, как правило поручаемых GA, является запуск тестирования. В простых случаях мы можем ограничиться ручным указанием тестовых данных прямо в файле workflow (или даже захардкодить их внутрь тестов). Однако, часто встречается ситуация, когда открытый показ и хранение данных невозможны. И тут у нас есть два пути:

  • Если данные - простые строчные переменные, не требующие обновления после выполнения тестирования, то можно использовать секреты репозитория
  • В тех случаях, когда информации много или операции с ней проще выполнять как с набором данных в отдельном файле (например, json), то нам поможет шифрование посредством gpg


Разберем оба пункта, но начнем с простого - с секретов
 

Секреты репозитория позволяют хранить пары ключ-значение в качестве настроек вашего проекта. Они крайне просты в использовании - вам достаточно лишь зайти в настройки  -> пункт Secrets and variables -> Actions и нажать New repository secret


 

Там можно выбрать имя секрета и его значение

 

После данной процедуры, сохраненный секрет будет доступен как переменная окружения в любых ваших GA процессах
 

${{ secrets.ИМЯСЕКРЕТА}}


 

Тут ничего сложного нет. Куда интереснее случаи, когда данных много, они - динамические, или же приложение вообще может работать только с файлами. Принцип построения процесса в данном случае таков:

  1. Формируется файл (на локальном компьютере, просто у себя), который будет содержать все необходимые данные в формате json (можно любой, но под json есть готовые инструменты)
  2. Этот файл шифруется при помощи gpg (GNU Privacy Guard). Он есть как под Linux (по умолчанию), так и под Windows (gpg4win)

    Использование именно gpg для нас оправдано, в первую очередь, наличием его установленным из коробки в линуксовых окружениях GA

    Пример команды для шифрования (проверено на Powershell и Bash)
    gpg --batch --symmetric --cipher-algo AES256 --passphrase="Ваша секретная фраза" vash_file.json
  3. Секретную фразу, используемую при шифровании, необходимо поместить в секреты репозитория, как мы рассматривали это ранее
  4. Зашифрованный файл отправляется в репозиторий (Не отправьте случайно обычный, а если не используете в проекте другие json файлы - лучше добавьте *.json в gitignore! Зашифрованный файл должен иметь расширение .gpg)

 

Имея зашифрованный файл и ключ для расшифровки в секретах репозитория, можно приступать к построению workflow - я создам полностью новый yml файл. Вводные данные такие: секретный файл называется super_secret_data.json.gpg, а секрет с секретной фразой - ENC_JSON

Так выглядит наш новый файл с первой работой - Decode

name: DecodeEncode

on:
  workflow_dispatch:

jobs:
  Decode:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Расшифруем файл
        run: gpg --quiet --batch --yes --decrypt --passphrase="${{ secrets.ENC_JSON }}" --output ./super_secret_data.json ./super_secret_data.json.gpg


Отдельно команда баша для расшифровки файла:
 

gpg --quiet --batch --yes --decrypt --passphrase="${{ secrets.ENC_JSON }}" --output ./super_secret_data.json ./super_secret_data.json.gpg

 

В результате данного действия в нашем репозитории (локальном на машине GA, не в публичном доступе) оказывается расшифрованный json файл. Мы можем использовать его прямо здесь, а можем отправить в новую работу. Второй вариант особенно актуален, когда работ, использующих одни и те же данные, несколько. Как это сделать?

 

Для переноса данных между работами используется кэш. В одной работе мы его записываем, а в последующих - читаем. Допишем в нашу работу Decode запись кэша
 

name: DecodeEncode

on:
  workflow_dispatch:

jobs:
  Decode:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Расшифруем файл
        run: gpg --quiet --batch --yes --decrypt --passphrase="${{ secrets.ENC_JSON }}" --output ./super_secret_data.json ./super_secret_data.json.gpg

      - name: Запишем тестовые данные в кэш
        uses: actions/cache/save@v3
        with:
          key: test-data
          path: ./super_secret_data.json

 

Для записи используется actions/cache/save, где в качестве параметров указываются ключ, по которому мы сможем в дальнейшем получить данные, а также путь, файлы которого мы кэшируем. В нашем случае, это super_secret_data.json. Добавим вторую работу, которая будет данный кэш получать:

 


name: DecodeEncode

on:
  workflow_dispatch:

jobs:
  Decode:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Расшифруем файл
        run: gpg --quiet --batch --yes --decrypt --passphrase="${{ secrets.ENC_JSON }}" --output ./super_secret_data.json ./super_secret_data.json.gpg

      - name: Запишем тестовые данные в кэш
        uses: actions/cache/save@v3
        with:
          key: test-data
          path: ./super_secret_data.json


  Read:
    needs: ["Decode"]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Получим тестовые данные из кэша
        uses: actions/cache/restore@v3
        with:
          key: test-data
          path: ./super_secret_data.json  



 

Для получения используется actions/cache/restore

На данном этапе мы можем использовать данные нашего файла в своих целях. Если это тестирование на OneScript, то, скорее всего, ввод данных будет осуществляться одним из 2-х вариантов:

  • В тестах захардкожен относительный путь к файлу
  • Данные принимаются аргументами командной строки

 

В первом случае никаких дополнительных действий не требуется - файл в папке у нас уже есть. Для второго же случая, существует очень хороший сторонний action - rgarcia-phi/json-to-variables

Данный action автоматически устанавливает все значения из json-файла в качестве переменных среды. При этом, указав параметр masked, все вытащенные значения (включая их дальнейшее использование уже в наших обработчиках) будут маскироваться звездочками





Добавим подобное и в наш файл. Для наглядности, не будем маскировать значения, а выведем их в echo:
 


name: DecodeEncode

on:
  workflow_dispatch:

jobs:
  Decode:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Расшифруем файл
        run: gpg --quiet --batch --yes --decrypt --passphrase="${{ secrets.ENC_JSON }}" --output ./super_secret_data.json ./super_secret_data.json.gpg

      - name: Запишем тестовые данные в кэш
        uses: actions/cache/save@v3
        with:
          key: test-data
          path: ./super_secret_data.json


  Read:
    needs: ["Decode"]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Получим тестовые данные из кэша
        uses: actions/cache/restore@v3
        with:
          key: test-data
          path: ./super_secret_data.json  

      - name: JSON в переменные
        uses: rgarcia-phi/json-to-variables@v1.1.0
        with:
          filename: 'super_secret_data.json'
          masked: false # !!! Установите true, если данные секретны !!!

      - name: Вывод значений
        run: |
            echo "${{ env.json_Secret1 }}"
            echo "${{ env.json_Secret2 }}"



Переменные определяются как ${{ env.префикс_ПолеИзJson }}. Префикс по умолчанию - json, но его можно поменять через with, как на скриншоте выше

Важно. Кириллические имена полей не работают и приводят к исключениям

 Посмотрим на результат:

 

Все отработало правильно: расшифрованные данные были получены из кэша, установлены как переменные и выведены в консоль

Помимо стандартного использования полученных данных - для работы с объектами внутри репозитория, подобные методы найдут место и в суровом 1С-way DevOps'е: записать в файлы или секреты адреса и пароли баз, после чего дергать их по http? Почему бы и нет

 

Если данные были изменены в процессе работы (например, обновились какие-нибудь временные токены), то их необходимо будет записать обратно. Добавим для этого третью работу в наш workflow:

 

name: DecodeEncode

on:
  workflow_dispatch:

jobs:
  Decode:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Расшифруем файл
        run: gpg --quiet --batch --yes --decrypt --passphrase="${{ secrets.ENC_JSON }}" --output ./super_secret_data.json ./super_secret_data.json.gpg

      - name: Запишем тестовые данные в кэш
        uses: actions/cache/save@v3
        with:
          key: test-data
          path: ./super_secret_data.json


  Read:
    needs: ["Decode"]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Получим тестовые данные из кэша
        uses: actions/cache/restore@v3
        with:
          key: test-data
          path: ./super_secret_data.json  

      - name: JSON в переменные
        uses: rgarcia-phi/json-to-variables@v1.1.0
        with:
          filename: 'super_secret_data.json'
          masked: false # !!! Установите true, если данные секретны !!!

      - name: Вывод значений
        run: |
            echo "${{ env.json_Secret1 }}"
            echo "${{ env.json_Secret2 }}"
      - name: Запишем измененные данные в кэш
        uses: actions/cache/save@v3
        with:
          key: test-data_new
          path: ./super_secret_data.json

  Encode:
      runs-on: ubuntu-latest
      needs: ["Read"]
      if: ${{ always() }}
      permissions:
        contents: write
        
      steps:

      - uses: actions/checkout@v2 
      
      - name: Получим тестовые данные из кэша
        uses: actions/cache/restore@v3
        with:
          key: test-data_new
          path: ./super_secret_data.json
          
      - name: Зашифровать данные обратно

        
        run: |
          rm -f ./super_secret_data.json.gpg
          gpg --batch --symmetric --cipher-algo AES256 --passphrase="${{ secrets.ENC_JSON }}" super_secret_data.json
          rm -f ./super_secret_data.json
          
      - name: Записать данные    
        uses: stefanzweifel/git-auto-commit-action@v5   


Что особенного мы тут видим?

Во-первых, это if: ${{ always() }}, так как данные должны быть сохранены обратно в любом случае, а также permissions: contents: write - разрешение на запись для action'а автокоммита, который сохранит наши изменения в репозиторий

Во-вторых, важно не забывать удалять незашифрованные файлы, если их нет в .gitignore

В-третьих, и, наверное, как самое главное - в работе Read мы записываем измененные данные под новым именем - test-data_new, под которым, собственно, потом их и получаем в Encode 

Тут кроется важный момент работы с кэшем

Дело в том, что изначальное предназначение кэша не столько в подобной передаче пользовательских данных из одной работы в другую, сколько в предоставлении возможности сохранять различные зависимости без необходимости их установки каждый раз: это у нас тут все просто, но во всяких node.js установка необходимых пакетов из package.json может занимать большую часть всего времени рабочего процесса. А ведь окружение при каждом запуске абсолютно чистое!

В связи с этим, кэш не удаляется самостоятельно при завершении работы и не позволяет перезаписывать себя по ключу - он не под это заточен. Но обойти это можно - двумя способами:

  • Использовать генерируемые данные в ключе: случайные символы, текущую дату и пр.
  • Чистить кэш после завершения работы

Если ваши тестовые данные не изменяются со временем, то вам это использовать не нужно. Но уже даже в случае нашего рабочего процесса из примера, при втором запуске все пойдет не так:

  1. При первом запуске, мы расшифровали данные и записали в кэш
  2. Изменили их и записали под другим ключом
  3. Зашифровали обратно и поместили в репозиторий
  4. При втором запуске мы расшифровываем измененные ранее данные и пытаемся их поместить в кэш
  5. Кэш с данным ключом уже существует, но в нем устаревшие данные. А заменить их новыми нельзя

 

 

Перейдем к решению. С первым вариантом все понятно - можно просто генерировать уникальное имя кэша. Но это как-то не круто. Лучше добавим еще один шаг после шифрования - очистку кэша:
 


name: DecodeEncode

on:
  workflow_dispatch:

jobs:
  Decode:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Расшифруем файл
        run: gpg --quiet --batch --yes --decrypt --passphrase="${{ secrets.ENC_JSON }}" --output ./super_secret_data.json ./super_secret_data.json.gpg

      - name: Запишем тестовые данные в кэш
        uses: actions/cache/save@v3
        with:
          key: test-data
          path: ./super_secret_data.json


  Read:
    needs: ["Decode"]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Получим тестовые данные из кэша
        uses: actions/cache/restore@v3
        with:
          key: test-data
          path: ./super_secret_data.json  

      - name: JSON в переменные
        uses: rgarcia-phi/json-to-variables@v1.1.0
        with:
          filename: 'super_secret_data.json'
          masked: false # !!! Установите true, если данные секретны !!!

      - name: Вывод значений
        run: |
            echo "${{ env.json_Secret1 }}"
            echo "${{ env.json_Secret2 }}"

      - name: Запишем измененные данные в кэш
        uses: actions/cache/save@v3
        with:
          key: test-data_new
          path: ./super_secret_data.json

  Encode:
      runs-on: ubuntu-latest
      needs: ["Read"]
      if: ${{ always() }}
      permissions:
        contents: write
        
      steps:

      - uses: actions/checkout@v2 
      
      - name: Получим тестовые данные из кэша
        uses: actions/cache/restore@v3
        with:
          key: test-data_new
          path: ./super_secret_data.json
          
      - name: Зашифровать данные обратно

        
        run: |
          rm -f ./super_secret_data.json.gpg
          gpg --batch --symmetric --cipher-algo AES256 --passphrase="$ENC_JSON" super_secret_data.json
          rm -f ./super_secret_data.json
        env:
          ENC_JSON: ${{ secrets.ENC_JSON }}
          
      - name: Записать данные    
        uses: stefanzweifel/git-auto-commit-action@v5   


  Clear-Cache:
    runs-on: ubuntu-latest
    needs: [Encode]
    if: ${{ always() }}
    steps:
      - name: Очистка test-data
        run: |
          curl -L \
          -X DELETE \
          -H "Accept: application/vnd.github+json" \
          -H "Authorization: Bearer ${{ secrets.TOKEN }}" \
          -H "X-GitHub-Api-Version: 2022-11-28" \
          "https://api.github.com/repos/Bayselonarrend/OpenIntegrations/actions/caches?key=test-data"

      - name: Очистка кэша test-data_new
        run: |
          curl -L \
          -X DELETE \
          -H "Accept: application/vnd.github+json" \
          -H "Authorization: Bearer ${{ secrets.TOKEN }}" \
          -H "X-GitHub-Api-Version: 2022-11-28" \
          "https://api.github.com/repos/Bayselonarrend/OpenIntegrations/actions/caches?key=test-data_new"

 

Делается это при помощи банальных http-запросов через curl. Ключ кэша указывается в конце URL и единственное, что вам тут еще необходимо - токен Github в секретах для авторизации запросов. Получить его можно в настройках аккаунта Github, перейдя по пункту Developer Settings (ссылка)

На крайний случай посмотреть список кэшей и удалить их руками можно на вкладке Actions -> Caches 

 

 

Неиспользуемые кэши удаляются автоматически спустя 7 дней


Артефакты

 

С кэшем разобрались - его можно записывать, читать и он хранится на Github вплоть до 7 дней без повторного использования

Механизм, который мы сейчас рассмотрим, во многом похож на кэш - он также позволяет записывать и передавать данные между работами, но служит для иных целей - это механизм артефактов

Артефакты - это файлы, производимые как результат деятельности рабочего процесса. Это могут быть логи, собранные бинарники или просто любые другие объекты, которые могут представлять для вас интерес. Их ключевым отличием от кэша является возможность скачивания со страницы процесса:

 

Так, например, вы можете создать рабочий процесс сборки и тестирования приложения (на том же OneScript), в результате которого получить исполняемый файл для релиза. Так это сейчас, хотя еще и в процессе разработки, происходит в ОПИ. Сюда же в тему и precommit1c - можно собирать файлы обработок/отчетов из исходников. Возможно, разберу это отдельно.

Помимо возможности скачивания руками, артефакты обладают возможностью быть переданными из одной работы в другую, но, несмотря на отсутствие проблем с очисткой, как у кэша, использовать их для передачи секретных данных нельзя - скачать артефакт может любой желающий, попавший на страницу выполнения workflow (если репозиторий публичный, конечно же)

Так выглядит step записи артефакта:
 

      - name: Записать артефакт
        uses: actions/upload-artifact@v4
        with:
          name: my-artifact-name
          path: ./my_cool_app.exe

 

А так - чтения:

      - name: Скачать артефакт с исполняемым файлом
        uses: actions/download-artifact@v4
        with:
          name: my-artifact-name


Ничего сложного. Больше про них и рассказать особо нечего

 

Полезные ссылки

 

Кроме тех вещей, о которых рассказано в статье, есть и другие решения, которые могут быть интересны при использовании Github Actions в сфере 1С/OS

  • Actions для 1С - это набор OS скриптов, которые предоставляют готовые решения для работы со многими популярными (и не очень) инструментами из мира 1С: Allure, Vanessa Automation, Coverage41C и др.

    Как я понимаю, они созданы в первую очередь для локального использования и для Gitlab, но кто нам запретит работать через GA, просто не с файлами репозитория, а с базой по http, правильно?
     
  • Autumn workflows - набор основных must-have экшенов для разработки библиотек на OneScript
  • setup-onescript - собственно, основной экшен для запуска вообще чего либо на OS под Github Actions. Устанавливает OneScript нужной версии без боли и заморочек
  • precommit1c - известный инструмент для разборки/сборки внешних обработок и отчетов. Скажу честно - сам еще не пробовал применять его в GA, но звучит это все интересно
  • osparser - парсер языка 1С. Очень гибкий инструмент с миллионом вариантов применения в своих скриптах по обработке исходников: хочешь делай каталоги методов в модулях, хочешь формируй автодокументацию на основе комментариев-описаний - как фантазия развернется. 
     

Autumn workflows и Actions для 1С порекомендовали знающие люди из комментариев к первой статье по теме. Если вы знаете еще какие-нибудь интересные решения, созданные для работы с Actions в сфере 1С - напишите их в комментарии, я добавлю в список.

Ну а пока все


Спасибо за внимание!

 

 

 Мой GitHub:     https://gitub.com/Bayselonarrend 
 Лицензия MIT:   https://mit-license.org

Github Actions Github Actions гитхаб CI Devops pipeline

См. также

Сайты и интернет-магазины WEB-интеграция Системный администратор Программист Пользователь Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM разных брендов в одной информационной базе в ручном и автоматическом режиме.

36000 руб.

03.08.2020    17782    19    22    

16

Сайты и интернет-магазины Интеграция WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 Управленческий учет Платные (руб)

Интеграция 1С и Битрикс 24. Разработка имеет двухстороннюю синхронизацию 1С и Bitrix24 задачами. Решение позволяет создавать пользователя в 1С из Битрикс24 и наоборот. Данная разработка технически подходит под все основные конфигурации линейки продуктов 1С:Предприятие 8.3 (платформа начиная с 8.3.23). При приобретении предоставляется 1 месяц бесплатных обновлений разработки. Доступна демо-версия продукта с подключением Вашего Битрикс24

5040 руб.

04.05.2021    19847    13    17    

16

WEB-интеграция 8.3.8 Конфигурации 1cv8 Автомобили, автосервисы Беларусь Украина Россия Казахстан Управленческий учет Платные (руб)

Расширение предназначено для конфигурации "1С:Предприятие 8. Управление Автотранспортом. ПРОФ". Функционал модуля: 1. Заполнение регистров сведений по подсистеме "Мониторинг", а именно: события по мониторингу, координаты по мониторингу, пробег и расход по мониторингу, текущее местоположение ТС по мониторингу 2. Заполнение путевого листа: пробег по мониторингу, время выезда/заезда, табличная часть ГСМ, места стоянок по геозонам. 3. Отчеты по данным загруженным в регистры сведений. 4. Предусмотрена автоматическая загрузка данных в фоновом режиме (условия работы данной загрузке читайте в описании товара) Модуль работает без включенной константы по настройкам мониторинга. Модуль формы предоставляется с открытым кодом, общий модуль защищен. Любой заинтересованный пользователь, имеет возможность скачать демо-версию расширения.

22656 руб.

25.05.2021    14422    42    8    

18

WEB-интеграция Программист Руководитель проекта Платформа 1С v8.3 Конфигурации 1cv8 1С:Франчайзи, автоматизация бизнеса Платные (руб)

Расширение значительно упрощает написание API на 1С. Веб программисты получают простой и понятный доступ к 1С. Описание API создаётся автоматически и представляется в виде удобном как для человека, так и для программной обработки.

24000 руб.

27.09.2024    1172    1    0    

3
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Snitkovski 88 05.04.24 15:16 Сейчас в теме
коллега, а что посоветуете для создания файлов CFU ?
мы активно используем GitHub Actions - всё, что нужно конвертируем "из EDT в XML", потом собираем, тестим (Платформой) синтаксис и применимость Расширений, собираем Дистрибутивный CF...

но есть вопрос с "изготовлением" CFU, для которых нужен CF предыдущего Релиза (предположим - только одного) - куда посоветуете его "подложить" / откуда вытянуть?
в Репозиторий складывать - как-то вообще не вариант... 8-/
2. bayselonarrend 2087 05.04.24 15:40 Сейчас в теме
(1)Я бы смотрел в сторону git lfs

https://edt.1c.ru/upload/docs_git/topics/t000132.html
https://docs.github.com/en/repositories/working-with-files/managing-large-files/installing-git-large-file-storage

В actions/checkout есть параметр lfs. Если его поставить в ture, то lfs файлы будут получаться вместе с репозиторием. В ридмике есть:

https://github.com/actions/checkout
3. Snitkovski 88 05.04.24 15:47 Сейчас в теме
(2) то есть, предлагается "напихать" многосотнемегабайтные CF'шники в Репозитории? - печально это... 8-(
4. bayselonarrend 2087 05.04.24 15:49 Сейчас в теме
(3)Ну это не совсем репозиторий - это именно что хранилище для больших бинарников поверх гита.
5. Snitkovski 88 05.04.24 16:01 Сейчас в теме
(4) при всём уважении - LFS это, конечно, "хранилище для больших бинарников", но В СаМОМ, что ни на есть, Репозитории! 8-/
и Репозитории - и так-то не сильно "тощие" - сразу о-о-очень сильно "толстеют" - и "таскать" всё это между всеми разработчиками, по всем программерским машинам - вообще не вариант! (моё личное мнение - не догма)
6. bayselonarrend 2087 05.04.24 16:50 Сейчас в теме
(5)Ну есть еще варианты, если чисто теоретически:

- Можно в окружении Github Actions получать/откатывать на нужный коммит в локальном репозитории - на последний для прошлого релиза. И тогда уже собирать CF, как вы его собираете в актуальной версии

- Можно делать релизы в самом репозитории (которые по тэгам на вкладке Release). Выходит новая версия -> Создается релиз с CF в ассетах. Потом эти ассеты можно получать по тэгам чем-нибудь вроде вот этого

https://github.com/marketplace/actions/release-downloader
Жолтокнижниг; +1 Ответить
Оставьте свое сообщение