Skip to content
Snippets Groups Projects
Select Git revision
  • eread/use-tw-team-docker-image-for-site-build-test-doc
  • fix/cyclonedx-upload-fail-non-english-dependency-path
  • dbickford/consolidate-version-script
  • main default protected
  • hhoerl/359825-fetch-sub-remotes
  • toon-use-new-git-clone
  • ajwalker/shell-wrap
  • cache-detect-bucket-location
  • k8s-promote-ff-retrieve-pod-warning-events
  • ggeorgiev/upgrade-ebpf
  • ajwalker/refactor-config-opts
  • bcarranza-use-correct-log_format-value
  • avonbertoldi/bump-go-to-1.23.5
  • 17-9-stable protected
  • axil-cherry-pick-hugo-shortcodes
  • 38586-windows-runner-does-not-capture-exit-code-0xffffffff-from-nuke-build-running-in-powershell-so
  • improve-concurrency-messages
  • ajwalker/runner-shell
  • ggeorgiev/trigger-k8s-wait-ubi
  • doc/clarify-allowed-pull-policies
  • helpers/runner_wrapper/api/v0.1.0 protected
  • v17.9.0 protected
  • v17.8.3 protected
  • v17.8.2 protected
  • v17.8.1 protected
  • v17.7.1 protected
  • v17.8.0 protected
  • v17.6.1 protected
  • v17.7.0 protected
  • v17.5.5 protected
  • v17.6.0 protected
  • v17.5.4 protected
  • v17.5.3 protected
  • v16.11.4 protected
  • v17.0.3 protected
  • v17.5.2 protected
  • v17.4.2 protected
  • v17.3.3 protected
  • v17.2.3 protected
  • v17.5.1 protected
40 results

builds_helper.go

Code owners
Assign users and groups as approvers for specific file changes. Learn more.
builds_helper.go 2.81 KiB
package commands

import (
	"sync"

	"gitlab.com/gitlab-org/gitlab-ci-multi-runner/common"

	"github.com/prometheus/client_golang/prometheus"
)

var numBuildsDesc = prometheus.NewDesc("ci_runner_builds", "The current number of running builds.", []string{"state", "stage"}, nil)

type buildsHelper struct {
	counts map[string]int
	builds []*common.Build
	lock   sync.Mutex
}

func (b *buildsHelper) acquire(runner *common.RunnerConfig) bool {
	b.lock.Lock()
	defer b.lock.Unlock()

	// Check number of builds
	count, _ := b.counts[runner.Token]
	if runner.Limit > 0 && count >= runner.Limit {
		// Too many builds
		return false
	}

	// Create a new build
	if b.counts == nil {
		b.counts = make(map[string]int)
	}
	b.counts[runner.Token]++
	return true
}

func (b *buildsHelper) release(runner *common.RunnerConfig) bool {
	b.lock.Lock()
	defer b.lock.Unlock()

	_, ok := b.counts[runner.Token]
	if ok {
		b.counts[runner.Token]--
		return true
	}
	return false
}

func (b *buildsHelper) addBuild(build *common.Build) {
	b.lock.Lock()
	defer b.lock.Unlock()

	runners := make(map[int]bool)
	projectRunners := make(map[int]bool)

	for _, otherBuild := range b.builds {
		if otherBuild.Runner.Token != build.Runner.Token {
			continue
		}
		runners[otherBuild.RunnerID] = true

		if otherBuild.ProjectID != build.ProjectID {
			continue
		}
		projectRunners[otherBuild.ProjectRunnerID] = true
	}

	for {
		if !runners[build.RunnerID] {
			break
		}
		build.RunnerID++
	}

	for {
		if !projectRunners[build.ProjectRunnerID] {
			break
		}
		build.ProjectRunnerID++
	}

	b.builds = append(b.builds, build)
	return
}

func (b *buildsHelper) removeBuild(deleteBuild *common.Build) bool {
	b.lock.Lock()
	defer b.lock.Unlock()

	for idx, build := range b.builds {
		if build == deleteBuild {
			b.builds = append(b.builds[0:idx], b.builds[idx+1:]...)
			return true
		}
	}
	return false
}

func (b *buildsHelper) buildsCount() int {
	b.lock.Lock()
	defer b.lock.Unlock()

	return len(b.builds)
}

func (b *buildsHelper) statesAndStages() map[common.BuildRuntimeState]map[common.BuildStage]int {
	b.lock.Lock()
	defer b.lock.Unlock()

	data := make(map[common.BuildRuntimeState]map[common.BuildStage]int)
	for _, build := range b.builds {
		if data[build.CurrentState] == nil {
			data[build.CurrentState] = make(map[common.BuildStage]int)
		}
		data[build.CurrentState][build.CurrentStage]++
	}
	return data
}

// Describe implements prometheus.Collector.
func (b *buildsHelper) Describe(ch chan<- *prometheus.Desc) {
	ch <- numBuildsDesc
}

// Collect implements prometheus.Collector.
func (b *buildsHelper) Collect(ch chan<- prometheus.Metric) {
	data := b.statesAndStages()

	for state, scripts := range data {
		for stage, count := range scripts {
			ch <- prometheus.MustNewConstMetric(numBuildsDesc, prometheus.GaugeValue, float64(count),
				string(state), string(stage))
		}
	}
}