Skip to content

Commit fe1acc0

Browse files
committed
add build repository with auto generated build date,sequence and alise
1 parent f4c7f9c commit fe1acc0

File tree

10 files changed

+270
-3
lines changed

10 files changed

+270
-3
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.flowci.build.business;
2+
3+
import com.flowci.build.model.Build;
4+
import com.flowci.common.model.Variables;
5+
6+
public interface TriggerBuild {
7+
/**
8+
* Trigger a new build
9+
*
10+
* @param flowId flow id
11+
* @param trigger trigger
12+
* @param inputs extra variables
13+
* @return build object
14+
*/
15+
Build invoke(Long flowId, Build.Trigger trigger, Variables inputs);
16+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.flowci.build.business.impl;
2+
3+
import com.flowci.build.business.TriggerBuild;
4+
import com.flowci.build.model.Build;
5+
import com.flowci.build.repo.BuildRepo;
6+
import com.flowci.build.repo.BuildYamlRepo;
7+
import com.flowci.common.model.Variables;
8+
import com.flowci.flow.business.FetchFlow;
9+
import lombok.AllArgsConstructor;
10+
import lombok.extern.slf4j.Slf4j;
11+
import org.springframework.stereotype.Component;
12+
13+
@Slf4j
14+
@Component
15+
@AllArgsConstructor
16+
public class TriggerBuildImpl implements TriggerBuild {
17+
18+
private final FetchFlow fetchFlow;
19+
20+
private final BuildRepo buildRepo;
21+
22+
private final BuildYamlRepo buildYamlRepo;
23+
24+
@Override
25+
public Build invoke(Long flowId, Build.Trigger trigger, Variables inputs) {
26+
return null;
27+
}
28+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package com.flowci.build.model;
2+
3+
import com.flowci.common.model.EntityBase;
4+
import jakarta.annotation.Nullable;
5+
import jakarta.persistence.*;
6+
import lombok.Data;
7+
import lombok.EqualsAndHashCode;
8+
import org.hibernate.annotations.Generated;
9+
import org.hibernate.generator.EventType;
10+
11+
import java.util.Set;
12+
13+
@Data
14+
@EqualsAndHashCode(callSuper = false, of = {"id"})
15+
@Entity
16+
@Table(name = "build")
17+
public class Build extends EntityBase {
18+
19+
public enum Trigger {
20+
MANUAL,
21+
API,
22+
SCHEDULED,
23+
GIT_PUSH,
24+
GIT_PR_OPEN,
25+
GIT_PR_CLOSE,
26+
GIT_TAG,
27+
}
28+
29+
public enum Status {
30+
CREATED, // init status
31+
LOADING, // when need to loading yaml from git
32+
QUEUED, // been put to job queue and waiting for agent
33+
ASSIGNED, // assigned to an agent
34+
RUNNING, // agent start to execute the flow
35+
CANCELLING, // will be cancelled, but waiting for response from agent
36+
SUCCESS,
37+
FAILURE,
38+
CANCELLED,
39+
TIMEOUT
40+
}
41+
42+
public static final Set<Status> FINAL_STATUS = Set.of(
43+
Status.SUCCESS,
44+
Status.FAILURE,
45+
Status.CANCELLED,
46+
Status.TIMEOUT
47+
);
48+
49+
@Id
50+
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "build_id_gen")
51+
@SequenceGenerator(name = "build_id_gen", sequenceName = "build_id_sequence", allocationSize = 1)
52+
private Long id;
53+
54+
private Long flowId;
55+
56+
// auto generated from db, YYYYMMMDD as integer
57+
@Generated(event = EventType.INSERT)
58+
@Column(name = "build_date", insertable = false, updatable = false, nullable = false)
59+
private Integer buildDate;
60+
61+
// auto generated from db, sequence ref to build date
62+
@Generated(event = EventType.INSERT)
63+
@Column(name = "build_sequence", insertable = false, updatable = false, nullable = false)
64+
private Long buildSequence;
65+
66+
// auto generated from db, <buildDate>.<buildSequence>
67+
@Generated(event = EventType.INSERT)
68+
@Column(name = "build_alias", insertable = false, updatable = false, nullable = false)
69+
private String buildAlias;
70+
71+
@Enumerated(EnumType.STRING)
72+
private Trigger trigger;
73+
74+
@Enumerated(EnumType.STRING)
75+
private Status status;
76+
77+
@Nullable
78+
private String commitHash;
79+
80+
@Nullable
81+
private Long agentId;
82+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.flowci.build.model;
2+
3+
import com.flowci.common.model.EntityBase;
4+
import com.flowci.common.model.Variables;
5+
import jakarta.persistence.Convert;
6+
import jakarta.persistence.Entity;
7+
import jakarta.persistence.Id;
8+
import jakarta.persistence.Table;
9+
import lombok.Data;
10+
import lombok.EqualsAndHashCode;
11+
12+
@Data
13+
@EqualsAndHashCode(callSuper = false, of = "buildId")
14+
@Entity
15+
@Table(name = "build_yaml")
16+
public class BuildYaml extends EntityBase {
17+
18+
@Id
19+
private Long id;
20+
21+
// ref to flow variables
22+
@Convert(converter = Variables.AttributeConverter.class)
23+
private Variables variables;
24+
25+
private String yaml;
26+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package com.flowci.build;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.flowci.build.repo;
2+
3+
import com.flowci.build.model.Build;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.stereotype.Repository;
6+
7+
@Repository
8+
public interface BuildRepo extends JpaRepository<Build, Long> {
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.flowci.build.repo;
2+
3+
import com.flowci.build.model.BuildYaml;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.stereotype.Repository;
6+
7+
@Repository
8+
public interface BuildYamlRepo extends JpaRepository<BuildYaml, Long> {
9+
}

src/main/resources/db/migration/V1__Init.sql

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
DROP SEQUENCE IF EXISTS flows_id_sequence;
2-
CREATE SEQUENCE flows_id_sequence START 10000 INCREMENT 1;
1+
-- flow related tables --
32

43
CREATE TABLE flows
54
(
@@ -16,6 +15,9 @@ CREATE TABLE flows
1615
updated_by BIGINT
1716
);
1817

18+
DROP SEQUENCE IF EXISTS flows_id_sequence;
19+
CREATE SEQUENCE flows_id_sequence START 10000 INCREMENT 1 OWNED BY flows.id;
20+
1921
CREATE TABLE flows_yaml
2022
(
2123
id BIGINT PRIMARY KEY,
@@ -34,5 +36,64 @@ CREATE TABLE flows_user
3436
created_by BIGINT,
3537
updated_at TIMESTAMP WITHOUT TIME ZONE NOT NULL,
3638
updated_by BIGINT,
37-
PRIMARY KEY(flow_id, user_id)
39+
PRIMARY KEY (flow_id, user_id)
40+
);
41+
42+
-- build related tables --
43+
44+
CREATE TABLE build
45+
(
46+
id BIGSERIAL PRIMARY KEY,
47+
flow_id BIGINT NOT NULL,
48+
build_date INTEGER NOT NULL,
49+
build_sequence BIGINT NOT NULL,
50+
build_alias varchar(50) NOT NULL,
51+
trigger varchar(20) NOT NULL,
52+
status varchar(20) NOT NULL,
53+
commit_hash varchar(40),
54+
agent_id BIGINT,
55+
created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL,
56+
created_by BIGINT,
57+
updated_at TIMESTAMP WITHOUT TIME ZONE NOT NULL,
58+
updated_by BIGINT,
59+
UNIQUE (flow_id, build_date, build_sequence)
60+
);
61+
62+
DROP SEQUENCE IF EXISTS build_id_sequence;
63+
CREATE SEQUENCE build_id_sequence START 10000 INCREMENT 1 OWNED BY build.id;
64+
65+
-- trigger function to create build_date, build_sequence and build_alias on insert
66+
CREATE OR REPLACE FUNCTION auto_build_sequence() RETURNS trigger AS
67+
$build_sequence$
68+
BEGIN
69+
SELECT to_char(current_date, 'YYYYMMDD')::INTEGER INTO NEW.build_date;
70+
71+
SELECT COALESCE(MAX(build_sequence) + 1, 1)
72+
INTO NEW.build_sequence
73+
FROM "build"
74+
WHERE flow_id = NEW.flow_id
75+
AND build_date = NEW.build_date;
76+
77+
SELECT concat(NEW.build_date, '.', NEW.build_sequence) INTO NEW.build_alias;
78+
79+
RETURN NEW;
80+
END;
81+
$build_sequence$ LANGUAGE plpgsql;
82+
83+
-- add trigger on insert
84+
CREATE TRIGGER build_sequence_trigger
85+
BEFORE INSERT
86+
ON "build"
87+
FOR EACH ROW
88+
EXECUTE PROCEDURE auto_build_sequence();
89+
90+
CREATE TABLE build_yaml
91+
(
92+
id BIGINT PRIMARY KEY,
93+
variables TEXT NOT NULL,
94+
yaml TEXT NOT NULL,
95+
created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL,
96+
created_by BIGINT,
97+
updated_at TIMESTAMP WITHOUT TIME ZONE NOT NULL,
98+
updated_by BIGINT
3899
);

src/test/java/com/flowci/SpringTestWithDB.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ static void setupDb(DynamicPropertyRegistry registry) {
2626
registry.add("spring.datasource.url", postgres::getJdbcUrl);
2727
registry.add("spring.datasource.username", postgres::getUsername);
2828
registry.add("spring.datasource.password", postgres::getPassword);
29+
registry.add("spring.jpa.show-sql", () -> "true");
2930
}
3031
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.flowci.build.repo;
2+
3+
4+
import com.flowci.SpringTestWithDB;
5+
import com.flowci.build.model.Build;
6+
import org.junit.jupiter.api.Test;
7+
import org.springframework.beans.factory.annotation.Autowired;
8+
9+
import static com.flowci.TestUtils.newDummyInstance;
10+
import static org.instancio.Select.field;
11+
import static org.junit.jupiter.api.Assertions.assertNotNull;
12+
13+
class BuildRepoTest extends SpringTestWithDB {
14+
15+
@Autowired
16+
private BuildRepo buildRepo;
17+
18+
@Test
19+
void givenBuild_whenSaving_thenBuildIsSaved() {
20+
var mockFlowId = 100L;
21+
var build = newDummyInstance(Build.class)
22+
.set(field(Build::getFlowId), mockFlowId)
23+
.ignore(field(Build::getId))
24+
.ignore(field(Build::getBuildDate))
25+
.ignore(field(Build::getBuildSequence))
26+
.ignore(field(Build::getBuildAlias))
27+
.create();
28+
29+
var saved = buildRepo.save(build);
30+
assertNotNull(saved.getBuildDate());
31+
assertNotNull(saved.getBuildSequence());
32+
assertNotNull(saved.getBuildSequence());
33+
}
34+
}

0 commit comments

Comments
 (0)