mirror of
https://github.com/semaphoreui/semaphore.git
synced 2025-01-20 15:29:28 +01:00
feat(ui): support build/deploy on UI
This commit is contained in:
parent
4ef6b5d484
commit
0f72ce182d
13
db/Store.go
13
db/Store.go
@ -26,25 +26,22 @@ type RetrieveQueryParams struct {
|
||||
SortInverted bool
|
||||
}
|
||||
|
||||
// ObjectProperties describe database entities.
|
||||
// It mainly used for NoSQL implementations (currently BoltDB) to preserve same
|
||||
// data structure of different implementations and easy change it if required.
|
||||
type ObjectProperties struct {
|
||||
TableName string
|
||||
IsGlobal bool // doesn't belong to other table, for example to project or user.
|
||||
ForeignColumnSuffix string
|
||||
PrimaryColumnName string
|
||||
SortableColumns []string
|
||||
SortInverted bool
|
||||
Type reflect.Type
|
||||
SortInverted bool // sort from high to low object ID by default. It is useful for some NoSQL implementations.
|
||||
Type reflect.Type // to which type the table bust be mapped.
|
||||
}
|
||||
|
||||
var ErrNotFound = errors.New("no rows in result set")
|
||||
var ErrInvalidOperation = errors.New("invalid operation")
|
||||
|
||||
func ValidateUsername(login string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type Transaction interface{}
|
||||
|
||||
type Store interface {
|
||||
Connect() error
|
||||
Close() error
|
||||
|
@ -25,8 +25,9 @@ type Template struct {
|
||||
VaultKeyID *int `db:"vault_key_id" json:"vault_key_id"`
|
||||
VaultKey AccessKey `db:"-" json:"-"`
|
||||
|
||||
StartVersion *string `db:"start_version" json:"start_version"`
|
||||
Type string `db:"type" json:"type"`
|
||||
Type string `db:"type" json:"type"`
|
||||
StartVersion *string `db:"start_version" json:"start_version"`
|
||||
BuildTemplateID *int `db:"build_template_id" json:"build_template_id"`
|
||||
}
|
||||
|
||||
func FillTemplate(d Store, template *Template) (err error) {
|
||||
@ -35,4 +36,3 @@ func FillTemplate(d Store, template *Template) (err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -22,3 +22,8 @@ type UserWithPwd struct {
|
||||
Pwd string `db:"-" json:"password"` // unhashed password from JSON
|
||||
User
|
||||
}
|
||||
|
||||
func ValidateUsername(login string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
alter table `project__template` add `type` varchar(10) not null default 'task';
|
||||
alter table `project__template` add `start_version` varchar(20);
|
||||
alter table project__template add `type` varchar(10) not null default 'task';
|
||||
alter table project__template add start_version varchar(20);
|
||||
alter table project__template add build_template_id int references project__template(id);
|
||||
alter table `task` add `version` varchar(20);
|
@ -10,8 +10,9 @@ func (d *SqlDb) CreateTemplate(template db.Template) (newTemplate db.Template, e
|
||||
insertID, err := d.insert(
|
||||
"id",
|
||||
"insert into project__template (project_id, inventory_id, repository_id, environment_id, " +
|
||||
"alias, playbook, arguments, override_args, description, vault_key_id)" +
|
||||
"values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
"alias, playbook, arguments, override_args, description, vault_key_id, `type`, start_version," +
|
||||
"build_template_id)" +
|
||||
"values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
template.ProjectID,
|
||||
template.InventoryID,
|
||||
template.RepositoryID,
|
||||
@ -21,7 +22,10 @@ func (d *SqlDb) CreateTemplate(template db.Template) (newTemplate db.Template, e
|
||||
template.Arguments,
|
||||
template.OverrideArguments,
|
||||
template.Description,
|
||||
template.VaultKeyID)
|
||||
template.VaultKeyID,
|
||||
template.Type,
|
||||
template.StartVersion,
|
||||
template.BuildTemplateID)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
@ -40,8 +44,19 @@ func (d *SqlDb) CreateTemplate(template db.Template) (newTemplate db.Template, e
|
||||
}
|
||||
|
||||
func (d *SqlDb) UpdateTemplate(template db.Template) error {
|
||||
_, err := d.exec("update project__template set inventory_id=?, repository_id=?, environment_id=?, alias=?, " +
|
||||
"playbook=?, arguments=?, override_args=?, description=?, vault_key_id=? " +
|
||||
_, err := d.exec("update project__template set " +
|
||||
"inventory_id=?, " +
|
||||
"repository_id=?, " +
|
||||
"environment_id=?, " +
|
||||
"alias=?, " +
|
||||
"playbook=?, " +
|
||||
"arguments=?, " +
|
||||
"override_args=?, " +
|
||||
"description=?, " +
|
||||
"vault_key_id=?, " +
|
||||
"`type`=?, " +
|
||||
"start_version=?," +
|
||||
"build_template_id=? " +
|
||||
"where removed = false and id=? and project_id=?",
|
||||
template.InventoryID,
|
||||
template.RepositoryID,
|
||||
@ -52,8 +67,12 @@ func (d *SqlDb) UpdateTemplate(template db.Template) error {
|
||||
template.OverrideArguments,
|
||||
template.Description,
|
||||
template.VaultKeyID,
|
||||
template.Type,
|
||||
template.StartVersion,
|
||||
template.BuildTemplateID,
|
||||
template.ID,
|
||||
template.ProjectID)
|
||||
template.ProjectID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -67,7 +86,8 @@ func (d *SqlDb) GetTemplates(projectID int, params db.RetrieveQueryParams) (temp
|
||||
"pt.playbook",
|
||||
"pt.arguments",
|
||||
"pt.override_args",
|
||||
"pt.vault_key_id").
|
||||
"pt.vault_key_id",
|
||||
"pt.`type`").
|
||||
From("project__template pt").
|
||||
Where("pt.removed = false")
|
||||
|
||||
|
@ -30,6 +30,39 @@
|
||||
placeholder="Example: site.yml"
|
||||
></v-text-field>
|
||||
|
||||
<v-select
|
||||
v-model="item.type"
|
||||
label="Type"
|
||||
:items="types"
|
||||
item-value="id"
|
||||
item-text="name"
|
||||
:rules="[v => !!v || 'Type is required']"
|
||||
required
|
||||
:disabled="formSaving"
|
||||
></v-select>
|
||||
|
||||
<v-text-field
|
||||
v-if="item.type === 'build'"
|
||||
v-model="item.start_version"
|
||||
label="Start Version"
|
||||
:rules="[v => !!v || 'Start Version is required']"
|
||||
required
|
||||
:disabled="formSaving"
|
||||
placeholder="Example: 0.0.0"
|
||||
></v-text-field>
|
||||
|
||||
<v-select
|
||||
v-if="item.type === 'deploy'"
|
||||
v-model="item.build_template_id"
|
||||
label="Build Template"
|
||||
:items="buildTemplates"
|
||||
item-value="id"
|
||||
item-text="alias"
|
||||
:rules="[v => !!v || 'Build Template is required']"
|
||||
required
|
||||
:disabled="formSaving"
|
||||
></v-select>
|
||||
|
||||
<v-select
|
||||
v-model="item.inventory_id"
|
||||
label="Inventory"
|
||||
@ -62,7 +95,9 @@
|
||||
required
|
||||
:disabled="formSaving"
|
||||
></v-select>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" md="6" class="pb-0">
|
||||
<v-select
|
||||
v-model="item.vault_key_id"
|
||||
label="Vault Password"
|
||||
@ -73,16 +108,6 @@
|
||||
:disabled="formSaving"
|
||||
></v-select>
|
||||
|
||||
<v-text-field
|
||||
v-model="cronFormat"
|
||||
label="Cron"
|
||||
:disabled="formSaving"
|
||||
placeholder="Example: * 1 * * * *"
|
||||
v-if="schedules.length <= 1"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" md="6" class="pb-0">
|
||||
<v-textarea
|
||||
outlined
|
||||
v-model="item.description"
|
||||
@ -105,6 +130,15 @@ Example:
|
||||
"-vvvv"
|
||||
]'
|
||||
/>
|
||||
|
||||
<v-text-field
|
||||
class="mt-6"
|
||||
v-model="cronFormat"
|
||||
label="Cron"
|
||||
:disabled="formSaving"
|
||||
placeholder="Example: * 1 * * * *"
|
||||
v-if="schedules.length <= 1"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-form>
|
||||
@ -149,6 +183,16 @@ export default {
|
||||
environment: null,
|
||||
schedules: null,
|
||||
cronFormat: null,
|
||||
types: [{
|
||||
id: 'task',
|
||||
name: 'Task',
|
||||
}, {
|
||||
id: 'build',
|
||||
name: 'Build',
|
||||
}, {
|
||||
id: 'deploy',
|
||||
name: 'Deploy',
|
||||
}],
|
||||
};
|
||||
},
|
||||
|
||||
@ -217,6 +261,13 @@ export default {
|
||||
url: `/api/project/${this.projectId}/environment`,
|
||||
responseType: 'json',
|
||||
})).data;
|
||||
|
||||
this.buildTemplates = (await axios({
|
||||
keys: 'get',
|
||||
url: `/api/project/${this.projectId}/templates?type=build`,
|
||||
responseType: 'json',
|
||||
})).data.filter((template) => template.type === 'build');
|
||||
|
||||
this.schedules = this.isNew ? [] : (await axios({
|
||||
keys: 'get',
|
||||
url: `/api/project/${this.projectId}/templates/${this.itemId}/schedules`,
|
||||
|
@ -1,35 +1,35 @@
|
||||
<template xmlns:v-slot="http://www.w3.org/1999/XSL/Transform">
|
||||
<div v-if="!isLoaded">
|
||||
<v-progress-linear
|
||||
indeterminate
|
||||
color="primary darken-2"
|
||||
indeterminate
|
||||
color="primary darken-2"
|
||||
></v-progress-linear>
|
||||
</div>
|
||||
<div v-else>
|
||||
<EditDialog
|
||||
:max-width="700"
|
||||
v-model="editDialog"
|
||||
save-button-text="Create"
|
||||
title="New template"
|
||||
@save="loadItems()"
|
||||
:max-width="700"
|
||||
v-model="editDialog"
|
||||
save-button-text="Create"
|
||||
title="New template"
|
||||
@save="loadItems()"
|
||||
>
|
||||
<template v-slot:form="{ onSave, onError, needSave, needReset }">
|
||||
<TemplateForm
|
||||
:project-id="projectId"
|
||||
item-id="new"
|
||||
@save="onSave"
|
||||
@error="onError"
|
||||
:need-save="needSave"
|
||||
:need-reset="needReset"
|
||||
:project-id="projectId"
|
||||
item-id="new"
|
||||
@save="onSave"
|
||||
@error="onError"
|
||||
:need-save="needSave"
|
||||
:need-reset="needReset"
|
||||
/>
|
||||
</template>
|
||||
</EditDialog>
|
||||
|
||||
<EditDialog
|
||||
v-model="newTaskDialog"
|
||||
save-button-text="Run"
|
||||
title="New Task"
|
||||
@save="onTaskCreated"
|
||||
v-model="newTaskDialog"
|
||||
save-button-text="Run"
|
||||
title="New Task"
|
||||
@save="onTaskCreated"
|
||||
>
|
||||
<template v-slot:title={}>
|
||||
<span class="breadcrumbs__item">{{ templateAlias }}</span>
|
||||
@ -39,13 +39,13 @@
|
||||
|
||||
<template v-slot:form="{ onSave, onError, needSave, needReset }">
|
||||
<TaskForm
|
||||
:project-id="projectId"
|
||||
item-id="new"
|
||||
:template-id="itemId"
|
||||
@save="onSave"
|
||||
@error="onError"
|
||||
:need-save="needSave"
|
||||
:need-reset="needReset"
|
||||
:project-id="projectId"
|
||||
item-id="new"
|
||||
:template-id="itemId"
|
||||
@save="onSave"
|
||||
@error="onError"
|
||||
:need-save="needSave"
|
||||
:need-reset="needReset"
|
||||
/>
|
||||
</template>
|
||||
</EditDialog>
|
||||
@ -55,20 +55,23 @@
|
||||
<v-toolbar-title>Task Templates</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn
|
||||
color="primary"
|
||||
@click="editItem('new')"
|
||||
class="mr-1"
|
||||
>New template</v-btn>
|
||||
color="primary"
|
||||
@click="editItem('new')"
|
||||
class="mr-1"
|
||||
>New template
|
||||
</v-btn>
|
||||
|
||||
<v-btn icon @click="settingsSheet = true"><v-icon>mdi-cog</v-icon></v-btn>
|
||||
<v-btn icon @click="settingsSheet = true">
|
||||
<v-icon>mdi-cog</v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar>
|
||||
|
||||
<v-data-table
|
||||
:headers="filteredHeaders"
|
||||
:items="items"
|
||||
hide-default-footer
|
||||
class="mt-4"
|
||||
:items-per-page="Number.MAX_VALUE"
|
||||
:headers="filteredHeaders"
|
||||
:items="items"
|
||||
hide-default-footer
|
||||
class="mt-4"
|
||||
:items-per-page="Number.MAX_VALUE"
|
||||
>
|
||||
<template v-slot:item.alias="{ item }">
|
||||
<router-link :to="`/project/${projectId}/templates/${item.id}`">
|
||||
@ -90,17 +93,17 @@
|
||||
|
||||
<template v-slot:item.actions="{ item }">
|
||||
<v-btn text color="black" class="pl-1 pr-2" @click="createTask(item.id)">
|
||||
<v-icon class="pr-1">mdi-play</v-icon>
|
||||
Run
|
||||
<v-icon class="pr-1">{{ getTemplateActionIcon(item) }}</v-icon>
|
||||
{{ getTemplateActionTitle(item) }}
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-data-table>
|
||||
|
||||
<TableSettingsSheet
|
||||
v-model="settingsSheet"
|
||||
table-name="project__template"
|
||||
:headers="headers"
|
||||
@change="onTableSettingsChange"
|
||||
v-model="settingsSheet"
|
||||
table-name="project__template"
|
||||
:headers="headers"
|
||||
@change="onTableSettingsChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@ -141,9 +144,9 @@ export default {
|
||||
|
||||
isLoaded() {
|
||||
return this.items
|
||||
&& this.inventory
|
||||
&& this.environment
|
||||
&& this.repositories;
|
||||
&& this.inventory
|
||||
&& this.environment
|
||||
&& this.repositories;
|
||||
},
|
||||
},
|
||||
|
||||
@ -154,6 +157,32 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
getTemplateActionIcon(item) {
|
||||
switch (item.type) {
|
||||
case 'task':
|
||||
return 'mdi-play';
|
||||
case 'build':
|
||||
return 'mdi-wrench';
|
||||
case 'deploy':
|
||||
return 'mdi-package-up';
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
},
|
||||
|
||||
getTemplateActionTitle(item) {
|
||||
switch (item.type) {
|
||||
case 'task':
|
||||
return 'Run';
|
||||
case 'build':
|
||||
return 'Build';
|
||||
case 'deploy':
|
||||
return 'Deploy';
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
},
|
||||
|
||||
createTask(itemId) {
|
||||
this.itemId = itemId;
|
||||
this.newTaskDialog = true;
|
||||
|
Loading…
Reference in New Issue
Block a user