shad-go/distbuild
Fedor Korotkiy 4be9a5a982 wip
2020-03-27 22:56:55 +03:00
..
README.md wip 2020-03-27 22:56:55 +03:00

distbuild

В этом задании вам нужно будет реализовать систему распределённой сборки.

Система сборки получает на вход граф сборки и файлы с исходным кодом. Результатом сборки являются исполняемые файлы и stderr/stdout запущенных процессов.

Граф сборки

Граф сборки состоит из джобов. Каждый джоб описывает команды, которые нужно запустить на одной машине, вместе со всеми входными файлами, которые нужны этим командам для работы.

Джобы в графе сборки запускают произвольные команды. Например, вызывать компилятор, линкер или запускать тесты.

Команды внутри джоба могут читать файлы с файловой системы. Мы будем различать два вида файлов:

  • Файлы с исходным кодом с машины пользователя.
  • Файлы, которые породили другие джобы.

Команды внутри джоба могут писать результаты своей работы в файлы на диске. Выходные файлы обязаны находиться внутри OUTPUT_DIR директории.

package graph

import "crypto/sha1"

// ID задаёт уникальный идентификатор джоба.
//
// Мы будем использовать sha1 хеш, поэтому ID будет занимать 20 байт.
type ID [sha1.Size]byte

// Job описывает одну вершину графа сборки.
type Job struct {
    // ID задаёт уникальный идентификатор джоба.
    //
    // ID вычисляется как хеш от всех входных файлов, команд запуска и хешей зависимых джобов.
    //
    // Выход джоба целиком опеределяется его ID. Это важное свойство позволяет кешировать
    // результаты сборки.
    ID ID

    // Name задаёт человекочитаемое имя джоба.
    //
    // Например:
    //   build gitlab.com/slon/disbuild/pkg/b
    //   vet gitlab.com/slon/disbuild/pkg/a
    //   test gitlab.com/slon/disbuild/pkg/test
    Name string

    // Inputs задаёт список файлов из директории с исходным кодом, 
    // которые нужны для работы этого джоба.
    //
    // В типичном случае, тут будут перечислены все .go файлы одного пакета.
    Inputs []string

    // Deps задаёт список джобов, выходы которых нужны для работы этого джоба.
    Deps []ID

    // Cmds описывает список команд, которые нужно выполнить в рамках этого джоба.
    Cmds []Cmd
}

// Cmd описывает одну команду сборки.
//
// Есть несколько видов команд. Все виды команд описываются одной структурой.
// Реальный тип определяется тем, какие поля структуры заполнены.
//
//   exec - выполняет произвольную команду
//   cat  - записывает строку в файл
//
// Все строки в описании команды могут содержать в себе на переменные. Перед выполнением
// реальной команды, переменные заменяются на их реальные значения.
//
//   {{OUTPUT_DIR}} - абсолютный путь до выходной директории джоба.
//   {{SOURCE_DIR}} - абсолютный путь до директории с исходными файлами.
//   {{DEP:f374b81d81f641c8c3d5d5468081ef83b2c7dae9}} - абсолютный путь до директории,
//   содержащей выход джоба с id f374b81d81f641c8c3d5d5468081ef83b2c7dae9.
type Cmd struct {
    // Exec описывает команду, которую нужно выполнить.
    Exec []string

    // Environ описывает переменные окружения, которые необходимы для работы команды из Exec.
    Environ []string
    
    // WorkingDirectory задаёт рабочую директорию для команды из Exec.
    WorkingDirectory string

    // CatTemplate задаёт шаблон строки, которую нужно записать в файл.
    CatTemplate string

    // CatOutput задаёт выходной файл для команды типа cat.
    CatOutput string
}

Архитектура системы

Наша система будет состоять из трех компонент.

  • Клиент - процесс запускающий сборку.
  • Воркер - процесс запускающий команды компиляции и тестирования.
  • Координатор - центральный процесс в системе, общается с клиентами и воркерами. Раздаёт задачи воркерам.

Типичная сборка выглядит так:

  1. Клиент подключается к координатору, посылает ему граф сборки и входные файлы для графа сборки.
  2. Кооринатор сохраняет граф сборки в памяти и начинает его исполнение.
  3. Воркеры начинают выполнять вершины графа, пересылая друг другу выходные директории джобов.
  4. Результаты работы джобов скачиваются на клиента.

Протокол: Клиент <-> Координатор

Протокол: Координатор <-> Воркер

Кеширование

Кеш исходного кода

Кеш артефактов

Тестирование