feat: build runtime releases from pinned Git branch commits
This commit is contained in:
+37
-20
@@ -35,6 +35,9 @@ func (a *API) ensureBuilds() error {
|
||||
"ALTER TABLE image_builds ADD COLUMN platform TEXT",
|
||||
"ALTER TABLE image_builds ADD COLUMN finished_at TEXT",
|
||||
"ALTER TABLE image_builds ADD COLUMN experimental INTEGER NOT NULL DEFAULT 0",
|
||||
"ALTER TABLE image_builds ADD COLUMN release_id TEXT NOT NULL DEFAULT ''",
|
||||
"ALTER TABLE image_builds ADD COLUMN source_repository TEXT NOT NULL DEFAULT ''",
|
||||
"ALTER TABLE image_builds ADD COLUMN source_commit TEXT NOT NULL DEFAULT ''",
|
||||
"CREATE TABLE IF NOT EXISTS image_admissions(image_id TEXT NOT NULL,version TEXT NOT NULL,recipe_rev TEXT NOT NULL,platform TEXT NOT NULL,state TEXT NOT NULL,evidence TEXT NOT NULL,admitted_by TEXT NOT NULL,admitted_at TEXT NOT NULL,PRIMARY KEY(image_id,version,recipe_rev,platform))",
|
||||
"ALTER TABLE images ADD COLUMN recipe_rev TEXT",
|
||||
"ALTER TABLE images ADD COLUMN platform TEXT",
|
||||
@@ -44,11 +47,11 @@ func (a *API) ensureBuilds() error {
|
||||
return e
|
||||
}
|
||||
}
|
||||
_, err = a.s.DB.Exec("DROP INDEX IF EXISTS image_builds_version; CREATE UNIQUE INDEX IF NOT EXISTS image_builds_identity ON image_builds(version,recipe_rev,platform) WHERE recipe_rev IS NOT NULL AND platform IS NOT NULL AND status IN ('queued','running','validating','success')")
|
||||
_, err = a.s.DB.Exec("DROP INDEX IF EXISTS image_builds_version; DROP INDEX IF EXISTS image_builds_identity; CREATE UNIQUE INDEX image_builds_identity ON image_builds(version,recipe_rev,platform) WHERE release_id='' AND recipe_rev IS NOT NULL AND platform IS NOT NULL AND status IN ('queued','running','validating','success'); CREATE UNIQUE INDEX IF NOT EXISTS image_builds_release_identity ON image_builds(source_repository,source_commit,release_id,platform) WHERE release_id<>'' AND status IN ('queued','running','validating','success')")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = a.s.DB.Exec("UPDATE image_builds SET status='failed',error='version requires administrator experimental build' WHERE status='queued' AND experimental=0 AND version NOT IN ('0.2.0-rc.1','0.2.0-rc.2')"); err != nil {
|
||||
if _, err = a.s.DB.Exec("UPDATE image_builds SET status='failed',error='version requires administrator experimental build' WHERE status='queued' AND release_id='' AND experimental=0 AND version NOT IN ('0.2.0-rc.1','0.2.0-rc.2')"); err != nil {
|
||||
return err
|
||||
}
|
||||
if !buildQueue.initialized[a.s.DB] {
|
||||
@@ -117,7 +120,7 @@ var errBuildRateLimited = errors.New("build limit: three new tasks per user per
|
||||
func (a *API) lookupActiveBuild(version string) (buildRecord, bool, error) {
|
||||
var b buildRecord
|
||||
var finished, recipe, platform sql.NullString
|
||||
err := a.s.DB.QueryRow("SELECT id,version,status,logs,error,image_id,created_at,requested_by,recipe_rev,platform,finished_at,experimental FROM image_builds WHERE version=? AND recipe_rev=? AND platform=? AND status IN ('queued','running','validating','success')", version, imageRecipeRev, imagePlatform).Scan(&b.ID, &b.Version, &b.Status, &b.Logs, &b.Error, &b.ImageID, &b.Created, &b.RequestedBy, &recipe, &platform, &finished, &b.Experimental)
|
||||
err := a.s.DB.QueryRow("SELECT id,version,status,logs,error,image_id,created_at,requested_by,recipe_rev,platform,finished_at,experimental FROM image_builds WHERE release_id='' AND version=? AND recipe_rev=? AND platform=? AND status IN ('queued','running','validating','success')", version, imageRecipeRev, imagePlatform).Scan(&b.ID, &b.Version, &b.Status, &b.Logs, &b.Error, &b.ImageID, &b.Created, &b.RequestedBy, &recipe, &platform, &finished, &b.Experimental)
|
||||
b.RecipeRev, b.Platform, b.Finished = recipe.String, platform.String, finished.String
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return b, false, nil
|
||||
@@ -280,7 +283,8 @@ func (a *API) startBuildWorkerLocked() {
|
||||
}
|
||||
buildQueue.Lock()
|
||||
var b buildRecord
|
||||
err := a.s.DB.QueryRow("SELECT id,version,experimental,requested_by FROM image_builds WHERE status='queued' ORDER BY created_at,id LIMIT 1").Scan(&b.ID, &b.Version, &b.Experimental, &b.RequestedBy)
|
||||
row := a.s.DB.QueryRow("SELECT " + buildSummaryColumns + " FROM image_builds WHERE status='queued' ORDER BY created_at,id LIMIT 1")
|
||||
err := scanBuildSummary(row, &b)
|
||||
if err == nil {
|
||||
_, err = a.s.DB.Exec("UPDATE image_builds SET status='running' WHERE id=?", b.ID)
|
||||
}
|
||||
@@ -345,7 +349,7 @@ func (a *API) runImageBuild(b buildRecord) {
|
||||
}
|
||||
}
|
||||
tarball, err := imageBuildContext()
|
||||
if !b.Experimental && !normalBuildAllowed(b.Version) {
|
||||
if b.ReleaseID == "" && !b.Experimental && !normalBuildAllowed(b.Version) {
|
||||
err = errBuildUnsupported
|
||||
}
|
||||
if b.Experimental {
|
||||
@@ -355,7 +359,10 @@ func (a *API) runImageBuild(b buildRecord) {
|
||||
}
|
||||
}
|
||||
var id string
|
||||
if err == nil {
|
||||
if b.ReleaseID != "" {
|
||||
tarball, err = a.releaseBuildContext(ctx, b)
|
||||
}
|
||||
if err == nil && b.ReleaseID == "" {
|
||||
id, err = a.localBuildImage(ctx, b.Version, "")
|
||||
}
|
||||
if err == nil && id == "" {
|
||||
@@ -365,11 +372,15 @@ func (a *API) runImageBuild(b buildRecord) {
|
||||
}
|
||||
}
|
||||
if err == nil && id == "" {
|
||||
id, err = a.docker.Build(ctx, tarball, b.Version, "dsh-web:"+b.Version+"-"+imageRecipeRev, appendLog)
|
||||
if b.ReleaseID == "" {
|
||||
id, err = a.docker.Build(ctx, tarball, b.Version, "dsh-web:"+b.Version+"-"+imageRecipeRev, appendLog)
|
||||
} else {
|
||||
id, err = a.docker.BuildRelease(ctx, tarball, b.Version, "dsh-web:release-"+b.SourceCommit, b.ReleaseID, b.SourceRepository, b.SourceCommit, appendLog)
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
var matches bool
|
||||
matches, err = a.imageMatches(ctx, id, b.Version)
|
||||
matches, err = a.buildImageMatches(ctx, id, b)
|
||||
if err == nil && !matches {
|
||||
err = errors.New("image template or platform mismatch")
|
||||
}
|
||||
@@ -517,18 +528,21 @@ type imageRecord struct {
|
||||
UsageCount int `json:"usage_count"`
|
||||
}
|
||||
type buildRecord struct {
|
||||
Experimental bool `json:"experimental"`
|
||||
ImageID string `json:"image_id,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Version string `json:"version"`
|
||||
Status string `json:"status"`
|
||||
Logs string `json:"logs,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
Created string `json:"created_at"`
|
||||
RequestedBy string `json:"requested_by,omitempty"`
|
||||
RecipeRev string `json:"recipe_rev,omitempty"`
|
||||
Platform string `json:"platform,omitempty"`
|
||||
Finished string `json:"finished_at,omitempty"`
|
||||
ReleaseID string `json:"release_id,omitempty"`
|
||||
SourceRepository string `json:"source_repository,omitempty"`
|
||||
SourceCommit string `json:"source_commit,omitempty"`
|
||||
Experimental bool `json:"experimental"`
|
||||
ImageID string `json:"image_id,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Version string `json:"version"`
|
||||
Status string `json:"status"`
|
||||
Logs string `json:"logs,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
Created string `json:"created_at"`
|
||||
RequestedBy string `json:"requested_by,omitempty"`
|
||||
RecipeRev string `json:"recipe_rev,omitempty"`
|
||||
Platform string `json:"platform,omitempty"`
|
||||
Finished string `json:"finished_at,omitempty"`
|
||||
}
|
||||
|
||||
func (a *API) images(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -721,6 +735,9 @@ func (a *API) localBuildImage(ctx context.Context, version, preferred string) (s
|
||||
return "", err
|
||||
}
|
||||
for _, im := range images {
|
||||
if preferred == "" && im.Labels["dsh-mgr.release"] != "" {
|
||||
continue
|
||||
}
|
||||
if im.ID != "" && im.Labels["dsh-mgr.role"] == "runtime" && im.Labels["dsh-mgr.version"] == version && im.Labels["dsh-mgr.recipe"] == imageRecipeRev && (preferred == "" || im.ID == preferred) {
|
||||
ok, err := a.imageMatches(ctx, im.ID, version)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user