public class ProjectAttributes {
private final String projectVersion;
private final String codePeriodVersion;
+ private final String buildString;
- public ProjectAttributes(@Nullable String projectVersion, String codePeriodVersion) {
+ public ProjectAttributes(@Nullable String projectVersion, String codePeriodVersion, String buildString) {
this.projectVersion = projectVersion;
this.codePeriodVersion = requireNonNull(codePeriodVersion, "codePeriod version can't be null");
+ this.buildString = buildString;
}
public ProjectAttributes(ProjectAttributes projectAttributes) {
this.projectVersion = projectAttributes.projectVersion;
this.codePeriodVersion = projectAttributes.codePeriodVersion;
+ this.buildString = projectAttributes.buildString;
}
public Optional<String> getProjectVersion() {
return codePeriodVersion;
}
+ public Optional<String> getBuildString() {
+ return Optional.ofNullable(buildString);
+ }
+
@Override
public String toString() {
return "ProjectAttributes{" +
"projectVersion='" + projectVersion + '\'' +
"codePeriodVersion='" + codePeriodVersion + '\'' +
+ "buildString='" + buildString + '\'' +
'}';
}
}
private static ProjectAttributes createProjectAttributes(ScannerReport.Metadata metadata, @Nullable SnapshotDto baseAnalysis) {
String projectVersion = trimToNull(metadata.getProjectVersion());
String codePeriodVersion = computeCodePeriodVersion(metadata.getCodePeriodVersion(), projectVersion, baseAnalysis);
- return new ProjectAttributes(projectVersion, codePeriodVersion);
+ String buildString = trimToNull(metadata.getBuildString());
+ return new ProjectAttributes(projectVersion, codePeriodVersion, buildString);
}
private static String computeCodePeriodVersion(String rawCodePeriodVersion, @Nullable String projectVersion, @Nullable SnapshotDto baseAnalysis) {
String componentUuid = component.getUuid();
String codePeriodVersion = component.getType() == PROJECT ? component.getProjectAttributes().getCodePeriodVersion() : null;
String projectVersion = component.getType() == PROJECT ? component.getProjectAttributes().getProjectVersion().orElse(null) : null;
+ String buildString = component.getType() == PROJECT ? component.getProjectAttributes().getBuildString().orElse(null) : null;
return new SnapshotDto()
.setUuid(snapshotUuid)
.setCodePeriodVersion(codePeriodVersion)
.setProjectVersion(projectVersion)
+ .setBuildString(buildString)
.setComponentUuid(componentUuid)
.setLast(false)
.setStatus(SnapshotDto.STATUS_UNPROCESSED)
import java.util.Arrays;
import java.util.Collections;
+import org.apache.commons.lang.RandomStringUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.ce.task.projectanalysis.component.Component.Status;
import static com.google.common.base.Strings.repeat;
+import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.sonar.ce.task.projectanalysis.component.Component.Type.FILE;
.setUuid("uuid_" + dbKey)
.setReportAttributes(ReportAttributes.newBuilder(dbKey.hashCode()).build());
if (type == PROJECT) {
- builder.setProjectAttributes(new ProjectAttributes(null, "version_1"));
+ String buildString = randomAlphabetic(15);
+ builder.setProjectAttributes(new ProjectAttributes(null, "version_1", buildString));
}
return builder;
}
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.Random;
import java.util.function.Function;
import javax.annotation.Nullable;
// both no project as "" or null should be supported
private static final ProjectAttributes SOME_PROJECT_ATTRIBUTES = new ProjectAttributes(
new Random().nextBoolean() ? null : randomAlphabetic(12),
- randomAlphabetic(20));
+ randomAlphabetic(20), randomAlphabetic(21));
@Rule
public ExpectedException expectedException = ExpectedException.none();
public void by_default_project_fields_are_loaded_from_report(@Nullable String projectVersion) {
String nameInReport = "the name";
String descriptionInReport = "the desc";
+ String buildString = randomAlphabetic(21);
Component root = call(newBuilder()
.setType(PROJECT)
.setKey(projectInDb.getKey())
.setRef(42)
.setName(nameInReport)
.setDescription(descriptionInReport)
- .build(), NO_SCM_BASE_PATH, new ProjectAttributes(projectVersion, "6.5"));
+ .build(), NO_SCM_BASE_PATH, new ProjectAttributes(projectVersion, "6.5", buildString));
assertThat(root.getUuid()).isEqualTo("generated_K1_uuid");
assertThat(root.getDbKey()).isEqualTo("generated_K1");
assertThat(root.getProjectAttributes().getProjectVersion()).contains(projectVersion);
}
assertThat(root.getProjectAttributes().getCodePeriodVersion()).isEqualTo("6.5");
+ assertThat(root.getProjectAttributes().getBuildString()).isEqualTo(Optional.of(buildString));
assertThatFileAttributesAreNotSet(root);
}
this.description = builder.description;
this.uuid = builder.uuid;
this.projectAttributes = Optional.ofNullable(builder.codePeriodVersion)
- .map(t -> new ProjectAttributes(builder.projectVersion, t))
+ .map(t -> new ProjectAttributes(builder.projectVersion, t, builder.buildString))
.orElse(null);
this.reportAttributes = ReportAttributes.newBuilder(builder.ref)
.build();
private String shortName;
private String codePeriodVersion;
private String projectVersion;
+ private String buildString;
private String description;
private FileAttributes fileAttributes;
private final List<Component> children = new ArrayList<>();
}
public Builder setCodePeriodVersion(String s) {
- checkCodePeriodVersion(s);
+ checkArgument(type != Type.PROJECT ^ s != null, "CodePeriod version must and can only be set on Project");
this.codePeriodVersion = s;
return this;
}
return this;
}
+ public Builder setBuildString(@Nullable String buildString) {
+ this.buildString = buildString;
+ return this;
+ }
+
public Builder setFileAttributes(FileAttributes fileAttributes) {
checkState(type == Type.FILE, "Only Component of type File can have File attributes");
this.fileAttributes = fileAttributes;
}
public ReportComponent build() {
- checkCodePeriodVersion(this.codePeriodVersion);
+ checkArgument(type != Type.PROJECT ^ this.codePeriodVersion != null, "CodePeriod version must and can only be set on Project");
+ checkArgument(type == Type.PROJECT || this.buildString == null, "BuildString can only be set on Project");
return new ReportComponent(this);
}
-
- private void checkCodePeriodVersion(@Nullable String s) {
- checkArgument(type != Type.PROJECT ^ s != null, "CodePeriod version must and can only be set on Project");
- }
}
-
}
import com.tngtech.java.junit.dataprovider.UseDataProvider;
import java.util.HashMap;
import java.util.Map;
+import java.util.Optional;
import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
assertThat(treeRootHolder.getReportTreeRoot().getProjectAttributes().getProjectVersion()).contains(projectVersion);
}
+ @Test
+ @UseDataProvider("oneParameterNullNonNullCombinations")
+ public void set_buildString(@Nullable String buildString) {
+ String projectVersion = randomAlphabetic(7);
+ String codePeriodVersion = randomAlphabetic(8);
+ setAnalysisMetadataHolder();
+ reportReader.setMetadata(createReportMetadata(projectVersion, codePeriodVersion, buildString));
+ reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
+
+ underTest.execute(new TestComputationStepContext());
+
+ assertThat(treeRootHolder.getReportTreeRoot().getProjectAttributes().getBuildString()).isEqualTo(Optional.ofNullable(buildString));
+ }
+
@DataProvider
public static Object[][] oneParameterNullNonNullCombinations() {
return new Object[][] {
}
public static ScannerReport.Metadata createReportMetadata(@Nullable String projectVersion, @Nullable String scannerCodePeriodVersion) {
+ return createReportMetadata(projectVersion, scannerCodePeriodVersion, null);
+ }
+
+ public static ScannerReport.Metadata createReportMetadata(@Nullable String projectVersion, @Nullable String scannerCodePeriodVersion, @Nullable String buildString) {
ScannerReport.Metadata.Builder builder = ScannerReport.Metadata.newBuilder()
.setProjectKey(REPORT_PROJECT_KEY)
.setRootComponentRef(ROOT_REF);
ofNullable(scannerCodePeriodVersion).ifPresent(builder::setCodePeriodVersion);
ofNullable(projectVersion).ifPresent(builder::setProjectVersion);
+ ofNullable(buildString).ifPresent(builder::setBuildString);
return builder.build();
}
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
import java.util.List;
+import java.util.Optional;
+import javax.annotation.Nullable;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@Test
@UseDataProvider("projectVersionOrNull")
- public void persist_analysis(String projectVersion) {
+ public void persist_analysis(@Nullable String projectVersion) {
OrganizationDto organizationDto = dbTester.organizations().insert();
ComponentDto projectDto = ComponentTesting.newPrivateProjectDto(organizationDto, "ABCD").setDbKey(PROJECT_KEY).setName("Project");
dbClient.componentDao().insert(dbTester.getSession(), projectDto);
Component file = ReportComponent.builder(Component.Type.FILE, 3).setUuid("DEFG").setKey("MODULE_KEY:src/main/java/dir/Foo.java").build();
Component directory = ReportComponent.builder(Component.Type.DIRECTORY, 2).setUuid("CDEF").setKey("MODULE_KEY:src/main/java/dir").addChildren(file).build();
+ String buildString = Optional.ofNullable(projectVersion).map(v -> randomAlphabetic(7)).orElse(null);
Component project = ReportComponent.builder(Component.Type.PROJECT, 1)
.setUuid("ABCD")
.setKey(PROJECT_KEY)
.setCodePeriodVersion("1.0")
.setProjectVersion(projectVersion)
+ .setBuildString(buildString)
.addChildren(directory)
.build();
treeRootHolder.setRoot(project);
assertThat(projectSnapshot.getComponentUuid()).isEqualTo(project.getUuid());
assertThat(projectSnapshot.getCodePeriodVersion()).isEqualTo("1.0");
assertThat(projectSnapshot.getProjectVersion()).isEqualTo(projectVersion);
+ assertThat(projectSnapshot.getBuildString()).isEqualTo(buildString);
assertThat(projectSnapshot.getLast()).isFalse();
assertThat(projectSnapshot.getStatus()).isEqualTo("U");
assertThat(projectSnapshot.getCreatedAt()).isEqualTo(analysisDate);
"ISLAST" BOOLEAN NOT NULL DEFAULT FALSE,
"VERSION" VARCHAR(500),
"PROJECT_VERSION" VARCHAR(100),
+ "BUILD_STRING" VARCHAR(100),
"PERIOD1_MODE" VARCHAR(100),
"PERIOD1_PARAM" VARCHAR(100),
"PERIOD1_DATE" BIGINT,
private Boolean last;
private String codePeriodVersion;
private String projectVersion;
+ private String buildString;
private String periodMode;
private String periodParam;
private Long periodDate;
this.projectVersion = projectVersion;
}
+ @CheckForNull
+ public String getBuildString() {
+ return buildString;
+ }
+
+ public SnapshotDto setBuildString(@Nullable String buildString) {
+ this.buildString = buildString;
+ return this;
+ }
+
public SnapshotDto setPeriodMode(@Nullable String p) {
periodMode = p;
return this;
s.islast as last,
s.version as rawCodePeriodVersion,
s.project_version as rawProjectVersion,
+ s.build_string as buildString,
s.period1_mode as periodMode,
s.period1_param as periodParam,
s.period1_date as periodDate
islast,
version,
project_version,
+ build_string,
period1_mode,
period1_param,
period1_date
#{last, jdbcType=BOOLEAN},
#{codePeriodVersion, jdbcType=VARCHAR},
#{projectVersion, jdbcType=VARCHAR},
+ #{buildString, jdbcType=VARCHAR},
#{periodMode, jdbcType=VARCHAR},
#{periodParam, jdbcType=VARCHAR},
#{periodDate, jdbcType=BIGINT}
build_date="1228222680000"
version="[null]"
project_version="[null]"
+ build_string="[null]"
/>
<analysis_properties uuid="u1"
snapshot_uuid="u1"
build_date="1228222680000"
version="[null]"
project_version="[null]"
+ build_string="[null]"
/>
<!-- snapshot with status "processed" and flagged as "last" -> do not purge and do not delete -->
build_date="1228222680000"
version="[null]"
project_version="[null]"
+ build_string="[null]"
/>
<!-- delete only resource 1 -->
build_date="1228222680000"
version="[null]"
project_version="[null]"
+ build_string="[null]"
/>
<project_measures id="1"
build_date="1228222680000"
version="[null]"
project_version="[null]"
+ build_string="[null]"
/>
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.db.migration.version.v77;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.SupportsBlueGreen;
+import org.sonar.server.platform.db.migration.def.VarcharColumnDef;
+import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+@SupportsBlueGreen
+public class AddBuildStringToSnapshot extends DdlChange {
+ private static final String TABLE_NAME = "snapshots";
+ private static final VarcharColumnDef COLUMN = newVarcharColumnDefBuilder()
+ .setColumnName("build_string")
+ .setIsNullable(true)
+ .setLimit(100)
+ .build();
+
+ public AddBuildStringToSnapshot(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new AddColumnsBuilder(getDialect(), TABLE_NAME)
+ .addColumn(COLUMN)
+ .build());
+ }
+}
.add(2608, "Delete favorites on not supported components", DeleteFavouritesOnNotSupportedComponentQualifiers.class)
.add(2609, "Delete exceeding favorites when there are more than 100 for a user", DeleteFavoritesExceedingOneHundred.class)
.add(2610, "Truncate ES_QUEUE table content", TruncateEsQueue.class)
-
+ .add(2611, "Add SNAPSHOTS.BUILD_STRING", AddBuildStringToSnapshot.class)
;
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.db.migration.version.v77;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.db.CoreDbTester;
+
+import static java.sql.Types.VARCHAR;
+
+public class AddBuildStringToSnapshotTest {
+
+ private static final String TABLE = "snapshots";
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+ @Rule
+ public final CoreDbTester db = CoreDbTester.createForSchema(AddBuildStringToSnapshotTest.class, "snapshots.sql");
+
+ private AddBuildStringToSnapshot underTest = new AddBuildStringToSnapshot(db.database());
+
+ @Test
+ public void creates_table_on_empty_db() throws SQLException {
+ underTest.execute();
+
+ db.assertColumnDefinition(TABLE, "project_version", VARCHAR, 100, true);
+ }
+
+ @Test
+ public void migration_is_not_reentrant() throws SQLException {
+ underTest.execute();
+
+ expectedException.expect(IllegalStateException.class);
+
+ underTest.execute();
+ }
+
+}
@Test
public void verify_migration_count() {
- verifyMigrationCount(underTest, 11);
+ verifyMigrationCount(underTest, 12);
}
}
--- /dev/null
+CREATE TABLE "SNAPSHOTS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "UUID" VARCHAR(50) NOT NULL,
+ "CREATED_AT" BIGINT,
+ "BUILD_DATE" BIGINT,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "STATUS" VARCHAR(4) NOT NULL DEFAULT 'U',
+ "PURGE_STATUS" INTEGER,
+ "ISLAST" BOOLEAN NOT NULL DEFAULT FALSE,
+ "VERSION" VARCHAR(500),
+ "PROJECT_VERSION" VARCHAR(100),
+ "PERIOD1_MODE" VARCHAR(100),
+ "PERIOD1_PARAM" VARCHAR(100),
+ "PERIOD1_DATE" BIGINT,
+ "PERIOD2_MODE" VARCHAR(100),
+ "PERIOD2_PARAM" VARCHAR(100),
+ "PERIOD2_DATE" BIGINT,
+ "PERIOD3_MODE" VARCHAR(100),
+ "PERIOD3_PARAM" VARCHAR(100),
+ "PERIOD3_DATE" BIGINT,
+ "PERIOD4_MODE" VARCHAR(100),
+ "PERIOD4_PARAM" VARCHAR(100),
+ "PERIOD4_DATE" BIGINT,
+ "PERIOD5_MODE" VARCHAR(100),
+ "PERIOD5_PARAM" VARCHAR(100),
+ "PERIOD5_DATE" BIGINT
+);
+CREATE INDEX "SNAPSHOT_COMPONENT" ON "SNAPSHOTS" ("COMPONENT_UUID");
+CREATE UNIQUE INDEX "ANALYSES_UUID" ON "SNAPSHOTS" ("UUID");