Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build ostree images that depend on commits #37

Merged
merged 20 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
5f9eee9
test: invert config map
achilleas-k Jul 19, 2023
f365c37
cmd/gen-manifests: new config map support
achilleas-k Jul 27, 2023
a9e0045
cmd/gen-manifests: config handling improvements
achilleas-k Jul 27, 2023
336616a
test/configs: new configs for pulling ostree commits
achilleas-k Jul 27, 2023
fcb208a
test: move pipeline generator one directory up
achilleas-k Jul 27, 2023
4077504
test: move common functions to a module
achilleas-k Jul 27, 2023
937821c
test: dynamic pipeline generator for ostree builds
achilleas-k Jul 24, 2023
ff4427c
test/generate-ostree-build-config: container context manager
achilleas-k Jul 28, 2023
639d9fb
test/imgtestlib: don't use skip list
achilleas-k Jul 28, 2023
a79f2a8
test: use temporary directories for build config gen
achilleas-k Jul 28, 2023
72ee42d
test/generate-ostree-build-config: write the build configs
achilleas-k Jul 28, 2023
e9a07f6
test: return manifest data when generating
achilleas-k Jul 31, 2023
41b828b
test: generate build configs for second child pipeline
achilleas-k Jul 30, 2023
073e8b8
test: install dependencies outside build scripts
achilleas-k Jul 30, 2023
4f0ad30
gitlab: define new stages and jobs
achilleas-k Jul 24, 2023
e96a27f
gitlab: run generator scripts with PYTHONUNBUFFERED
achilleas-k Jul 30, 2023
15dee4c
gitlab: formatting fixes
achilleas-k Jul 31, 2023
661104c
gitlab: separate pipeline generators per architecture
achilleas-k Jul 31, 2023
065820c
test: document image build tests in README
achilleas-k Jul 31, 2023
bc31f93
test/README: describe and link to example project
achilleas-k Jul 31, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 86 additions & 5 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
---
stages:
- init
- gen
- test
- gen-ostree
- test-ostree
- finish

variables:
# Set the parent pipeline ID as a global variable so that the child pipeline
# jobs can use it to retrieve artifacts.
PARENT_PIPELINE_ID: $CI_PIPELINE_ID

.base:
before_script:
- mkdir -p /tmp/artifacts
- schutzbot/ci_details.sh > /tmp/artifacts/ci-details-before-run.txt
- cat schutzbot/team_ssh_keys.txt | tee -a ~/.ssh/authorized_keys > /dev/null
- cat schutzbot/team_ssh_keys.txt |
tee -a ~/.ssh/authorized_keys > /dev/null
after_script:
- schutzbot/ci_details.sh > /tmp/artifacts/ci-details-after-run.txt || true
- schutzbot/update_github_status.sh update || true
Expand Down Expand Up @@ -37,26 +46,98 @@ init:
script:
- schutzbot/update_github_status.sh start

generate-build-config:
generate-build-config-x86_64:
stage: gen
extends: .terraform
variables:
RUNNER: aws/fedora-38-x86_64
INTERNAL_NETWORK: "true"
PYTHONUNBUFFERED: 1
script:
- sudo dnf -y install go python3 gpgme-devel s3cmd
osbuild osbuild-luks2 osbuild-lvm2 osbuild-ostree osbuild-selinux
- ./test/generate-build-config build-config.yml
artifacts:
paths:
- build-config.yml

generate-build-config-aarch64:
stage: gen
extends: .terraform
variables:
RUNNER: aws/fedora-38-aarch64
INTERNAL_NETWORK: "true"
PYTHONUNBUFFERED: 1
script:
- sudo dnf -y install go python3 gpgme-devel s3cmd
osbuild osbuild-luks2 osbuild-lvm2 osbuild-ostree osbuild-selinux
- ./test/cases/generate-build-config build-config.yml
- ./test/generate-build-config build-config.yml
artifacts:
paths:
- build-config.yml

image-build-trigger:
image-build-trigger-x86_64:
stage: test
trigger:
include:
- artifact: build-config.yml
job: generate-build-config
job: generate-build-config-x86_64
strategy: depend

image-build-trigger-aarch64:
stage: test
trigger:
include:
- artifact: build-config.yml
job: generate-build-config-aarch64
strategy: depend

generate-ostree-build-config-x86_64:
stage: gen-ostree
extends: .terraform
variables:
RUNNER: aws/fedora-38-x86_64
INTERNAL_NETWORK: "true"
PYTHONUNBUFFERED: 1
script:
- sudo dnf -y install go python3 gpgme-devel s3cmd
osbuild osbuild-luks2 osbuild-lvm2 osbuild-ostree osbuild-selinux podman
- ./test/generate-ostree-build-config build-config.yml build-configs
artifacts:
paths:
- build-config.yml
- build-configs

generate-ostree-build-config-aarch64:
stage: gen-ostree
extends: .terraform
variables:
RUNNER: aws/fedora-38-aarch64
INTERNAL_NETWORK: "true"
PYTHONUNBUFFERED: 1
script:
- sudo dnf -y install go python3 gpgme-devel s3cmd
osbuild osbuild-luks2 osbuild-lvm2 osbuild-ostree osbuild-selinux podman
- ./test/generate-ostree-build-config build-config.yml build-configs
artifacts:
paths:
- build-config.yml
- build-configs

image-build-ostree-trigger-x86_64:
stage: test-ostree
trigger:
include:
- artifact: build-config.yml
job: generate-ostree-build-config-x86_64
strategy: depend

image-build-ostree-trigger-aarch64:
stage: test-ostree
trigger:
include:
- artifact: build-config.yml
job: generate-ostree-build-config-aarch64
strategy: depend

finish:
Expand Down
119 changes: 96 additions & 23 deletions cmd/gen-manifests/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,68 @@ type buildRequest struct {
Arch string `json:"arch,omitempty"`
ImageType string `json:"image-type,omitempty"`
Repositories []repository `json:"repositories,omitempty"`
Config *buildConfig `json:"config"`
Config *BuildConfig `json:"config"`
}

type buildConfig struct {
type BuildConfig struct {
Name string `json:"name"`
OSTree *ostreeOptions `json:"ostree,omitempty"`
Blueprint *crBlueprint `json:"blueprint,omitempty"`
}

type configMap map[string][]buildConfig
type BuildDependency struct {
Config string `json:"config"`
ImageType string `json:"image-type"`
}

// BuildConfigs is a nested map representing the configs to use for each
// distro/arch/image-type. If any component is empty, it maps to all values.
type BuildConfigs map[string]map[string]map[string][]BuildConfig

func (bc BuildConfigs) Insert(distro, arch, imageType string, cfg BuildConfig) {
distroCfgs := bc[distro]
if distroCfgs == nil {
distroCfgs = make(map[string]map[string][]BuildConfig)
}

distroArchCfgs := distroCfgs[arch]
if distroArchCfgs == nil {
distroArchCfgs = make(map[string][]BuildConfig)
}

distroArchItCfgs := distroArchCfgs[imageType]
if distroArchItCfgs == nil {
distroArchItCfgs = make([]BuildConfig, 0)
}

distroArchItCfgs = append(distroArchItCfgs, cfg)
distroArchCfgs[imageType] = distroArchItCfgs
distroCfgs[arch] = distroArchCfgs
bc[distro] = distroCfgs
}

func loadConfig(path string) buildConfig {
func (bc BuildConfigs) Get(distro, arch, imageType string) []BuildConfig {
configs := make([]BuildConfig, 0)
for distroName, distroCfgs := range bc {
distroGlob := glob.MustCompile(distroName)
if distroGlob.Match(distro) {
for archName, distroArchCfgs := range distroCfgs {
archGlob := glob.MustCompile(archName)
if archGlob.Match(arch) {
for itName, distroArchItCfgs := range distroArchCfgs {
itGlob := glob.MustCompile(itName)
if itGlob.Match(imageType) {
configs = append(configs, distroArchItCfgs...)
}
}
}
}
}
}
return configs
}

func loadConfig(path string) BuildConfig {
fp, err := os.Open(path)
if err != nil {
panic(fmt.Sprintf("failed to open config %q: %s", path, err.Error()))
Expand All @@ -102,14 +152,21 @@ func loadConfig(path string) buildConfig {
if err != nil {
panic(fmt.Sprintf("failed to read config %q: %s", path, err.Error()))
}
var conf buildConfig
var conf BuildConfig
if err := json.Unmarshal(data, &conf); err != nil {
panic(fmt.Sprintf("failed to unmarshal config %q: %s", path, err.Error()))
}
return conf
}

func loadConfigMap(configPath string) configMap {
func loadConfigMap(configPath string) BuildConfigs {
type configFilters struct {
ImageTypes []string `json:"image-types"`
Distros []string `json:"distros"`
Arches []string `json:"arches"`
}
type configMap map[string]configFilters

fp, err := os.Open(configPath)
if err != nil {
panic(fmt.Sprintf("failed to open config map %q: %s", configPath, err.Error()))
Expand All @@ -119,19 +176,36 @@ func loadConfigMap(configPath string) configMap {
if err != nil {
panic(fmt.Sprintf("failed to read config map %q: %s", configPath, err.Error()))
}
configPaths := make(map[string][]string)
if err := json.Unmarshal(data, &configPaths); err != nil {
var cfgMap configMap
if err := json.Unmarshal(data, &cfgMap); err != nil {
panic(fmt.Sprintf("failed to unmarshal config map %q: %s", configPath, err.Error()))
}

emptyFallback := func(list []string) []string {
if len(list) == 0 {
// empty list means everything so let's add the * to catch
// everything with glob
return []string{"*"}
}
return list
}

// load each config from its path
cm := make(configMap)
for it, paths := range configPaths {
configs := make([]buildConfig, len(paths))
for idx, path := range paths {
configs[idx] = loadConfig(path)
cm := make(BuildConfigs)
for path, filters := range cfgMap {
// config paths can be relative to the location of the config map
if !filepath.IsAbs(path) {
cfgDir := filepath.Dir(configPath)
path = filepath.Join(cfgDir, path)
}
config := loadConfig(path)
for _, d := range emptyFallback(filters.Distros) {
for _, a := range emptyFallback(filters.Arches) {
for _, it := range emptyFallback(filters.ImageTypes) {
cm.Insert(d, a, it, config)
}
}
}
cm[it] = configs
}

return cm
Expand All @@ -142,7 +216,7 @@ type manifestJob func(chan string) error
func makeManifestJob(
name string,
imgType distro.ImageType,
bc buildConfig,
bc BuildConfig,
distribution distro.Distro,
repos []repository,
archName string,
Expand Down Expand Up @@ -512,12 +586,13 @@ func main() {
// common args
var outputDir, cacheRoot, configPath string
var nWorkers int
var metadata bool
var metadata, skipNoconfig bool
flag.StringVar(&outputDir, "output", "test/data/manifests/", "manifest store directory")
flag.IntVar(&nWorkers, "workers", 16, "number of workers to run concurrently")
flag.StringVar(&cacheRoot, "cache", "/tmp/rpmmd", "rpm metadata cache directory")
flag.BoolVar(&metadata, "metadata", true, "store metadata in the file")
flag.StringVar(&configPath, "config", "test/config-map.json", "configuration file mapping image types to configs")
flag.BoolVar(&skipNoconfig, "skip-noconfig", false, "skip distro-arch-image configurations that have no config (otherwise fail)")

// content args
var packages, containers, commits bool
Expand Down Expand Up @@ -589,14 +664,12 @@ func main() {
continue
}

imgTypeConfigs := configs[imgTypeName]
if len(imgTypeConfigs) == 0 {
// No configs specified. Use default.
imgTypeConfigs = configs["default"]
}

imgTypeConfigs := configs.Get(distroName, archName, imgTypeName)
if len(imgTypeConfigs) == 0 {
panic(fmt.Sprintf("no configs found for image type %q and no default defined", imgTypeName))
if skipNoconfig {
continue
}
panic(fmt.Sprintf("no configs defined for image type %q", imgTypeName))
}

for _, itConfig := range imgTypeConfigs {
Expand Down
Loading
Loading