registry | registry | ||||
.add(2800, "Truncate environment variables and system properties from existing scanner reports", | .add(2800, "Truncate environment variables and system properties from existing scanner reports", | ||||
TruncateEnvAndSystemVarsFromScannerContext.class) | TruncateEnvAndSystemVarsFromScannerContext.class) | ||||
.add(2801, "populate install version and install date internal properties", PopulateInstallDateAndVersion.class); | |||||
.add(2801, "populate install version and install date internal properties", PopulateInstallDateAndVersion.class) | |||||
.add(2802, "Migrate property 'sonar.pullrequest.provider' value from VSTS to Azure DevOps", MigrateVstsProviderToAzureDevOps.class); | |||||
} | } | ||||
} | } |
/* | |||||
* 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.v79; | |||||
import java.sql.SQLException; | |||||
import org.sonar.db.Database; | |||||
import org.sonar.server.platform.db.migration.SupportsBlueGreen; | |||||
import org.sonar.server.platform.db.migration.step.DataChange; | |||||
import org.sonar.server.platform.db.migration.step.MassUpdate; | |||||
@SupportsBlueGreen | |||||
public class MigrateVstsProviderToAzureDevOps extends DataChange { | |||||
private static final String VSTS = "VSTS"; | |||||
private static final String VSTS_TFS = "VSTS / TFS"; | |||||
public MigrateVstsProviderToAzureDevOps(Database db) { | |||||
super(db); | |||||
} | |||||
@Override | |||||
protected void execute(Context context) throws SQLException { | |||||
MassUpdate massUpdate = context.prepareMassUpdate(); | |||||
massUpdate.select("select id, text_value from properties " + | |||||
" where prop_key = 'sonar.pullrequest.provider' and text_value in ('" + VSTS + "', '" + VSTS_TFS + "')"); | |||||
massUpdate.update("update properties " + | |||||
" set text_value= ?, " + | |||||
" clob_value = null " + | |||||
" where id = ?"); | |||||
massUpdate.rowPluralName("PR provider properties"); | |||||
massUpdate.execute((row, update) -> { | |||||
update.setString(1, convert(row.getString(2))); | |||||
update.setLong(2, row.getLong(1)); | |||||
return true; | |||||
}); | |||||
} | |||||
private static String convert(String oldValue) { | |||||
switch (oldValue) { | |||||
case VSTS: | |||||
return "Azure DevOps Services"; | |||||
case VSTS_TFS: | |||||
return "Azure DevOps Services/Server"; | |||||
default: | |||||
throw new IllegalStateException("Unexpected value: " + oldValue); | |||||
} | |||||
} | |||||
} |
@Test | @Test | ||||
public void verify_migration_count() { | public void verify_migration_count() { | ||||
verifyMigrationCount(underTest, 2); | |||||
verifyMigrationCount(underTest, 3); | |||||
} | } | ||||
} | } |
/* | |||||
* 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.v79; | |||||
import java.sql.SQLException; | |||||
import java.util.HashMap; | |||||
import java.util.stream.Collectors; | |||||
import javax.annotation.Nullable; | |||||
import org.assertj.core.groups.Tuple; | |||||
import org.junit.Rule; | |||||
import org.junit.Test; | |||||
import org.sonar.db.CoreDbTester; | |||||
import static org.assertj.core.api.Assertions.assertThat; | |||||
import static org.assertj.core.api.Assertions.tuple; | |||||
public class MigrateVstsProviderToAzureDevOpsTest { | |||||
private final static String SELECT_PROPERTIES = "SELECT prop_key, is_empty, text_value, clob_value FROM properties"; | |||||
@Rule | |||||
public CoreDbTester db = CoreDbTester.createForSchema(MigrateVstsProviderToAzureDevOpsTest.class, "properties.sql"); | |||||
private MigrateVstsProviderToAzureDevOps underTest = new MigrateVstsProviderToAzureDevOps(db.database()); | |||||
@Test | |||||
public void migration_must_update_the_database() throws SQLException { | |||||
insertProperty("sonar.pullrequest.provider", "any.value_here", null, false); | |||||
insertProperty("sonar.pullrequest.provider", "VSTS", null, false); | |||||
insertProperty("sonar.pullrequest.provider", "VSTS / TFS", null, false); | |||||
insertProperty("whatever.property", "nothingspecial", null, false); | |||||
insertProperty("whatever.property", null, "nothing.special", false); | |||||
underTest.execute(); | |||||
assertPropertyContainsInAnyOrder( | |||||
tuple("sonar.pullrequest.provider", "any.value_here", null, false), | |||||
tuple("sonar.pullrequest.provider", "Azure DevOps Services", null, false), | |||||
tuple("sonar.pullrequest.provider", "Azure DevOps Services/Server", null, false), // Single change | |||||
tuple("whatever.property", "nothingspecial", null, false), | |||||
tuple("whatever.property", null, "nothing.special", false) | |||||
); | |||||
} | |||||
@Test | |||||
public void migration_must_be_reentrant() throws SQLException { | |||||
insertProperty("sonar.pullrequest.provider", "any.value_here", null, false); | |||||
insertProperty("sonar.pullrequest.provider", "VSTS", null, false); | |||||
insertProperty("sonar.pullrequest.provider", "VSTS / TFS", null, false); | |||||
insertProperty("whatever.property", "nothingspecial", null, false); | |||||
insertProperty("whatever.property", null, "nothing.special", false); | |||||
underTest.execute(); | |||||
underTest.execute(); | |||||
assertPropertyContainsInAnyOrder( | |||||
tuple("sonar.pullrequest.provider", "any.value_here", null, false), | |||||
tuple("sonar.pullrequest.provider", "Azure DevOps Services", null, false), | |||||
tuple("sonar.pullrequest.provider", "Azure DevOps Services/Server", null, false), // Single change | |||||
tuple("whatever.property", "nothingspecial", null, false), | |||||
tuple("whatever.property", null, "nothing.special", false) | |||||
); | |||||
} | |||||
@Test | |||||
public void migration_is_doing_nothing_when_no_data() throws SQLException { | |||||
assertThat(db.countRowsOfTable("properties")).isEqualTo(0); | |||||
underTest.execute(); | |||||
assertThat(db.countRowsOfTable("properties")).isEqualTo(0); | |||||
} | |||||
private void insertProperty(String propKey, @Nullable String textValue, @Nullable String clobValue, boolean isEmpty) { | |||||
HashMap<String, Object> map = new HashMap<>(); | |||||
map.put("PROP_KEY", propKey); | |||||
map.put("TEXT_VALUE", textValue); | |||||
map.put("CLOB_VALUE", clobValue); | |||||
map.put("IS_EMPTY", isEmpty); | |||||
db.executeInsert("PROPERTIES", map); | |||||
} | |||||
private void assertPropertyContainsInAnyOrder(Tuple... tuples) { | |||||
assertThat(db.select(SELECT_PROPERTIES) | |||||
.stream() | |||||
.map(p -> new Tuple(p.get("PROP_KEY"), p.get("TEXT_VALUE"), p.get("CLOB_VALUE"), p.get("IS_EMPTY"))) | |||||
.collect(Collectors.toList())) | |||||
.containsExactlyInAnyOrder(tuples); | |||||
} | |||||
} |
CREATE TABLE "PROPERTIES" ( | |||||
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), | |||||
"PROP_KEY" VARCHAR(512) NOT NULL, | |||||
"RESOURCE_ID" INTEGER, | |||||
"USER_ID" INTEGER, | |||||
"IS_EMPTY" BOOLEAN NOT NULL, | |||||
"TEXT_VALUE" VARCHAR(4000), | |||||
"CLOB_VALUE" CLOB, | |||||
"CREATED_AT" BIGINT | |||||
); | |||||
CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES" ("PROP_KEY"); | |||||
onboarding.project_analysis.commands_for_analysis=Below are the commands to use to do an analysis. | onboarding.project_analysis.commands_for_analysis=Below are the commands to use to do an analysis. | ||||
onboarding.project_analysis.guide_to_integrate_pipelines=follow the guide to integrating with Pipelines | onboarding.project_analysis.guide_to_integrate_pipelines=follow the guide to integrating with Pipelines | ||||
onboarding.project_analysis.guide_to_integrate_travis=follow the guide to integrating with Travis CI | onboarding.project_analysis.guide_to_integrate_travis=follow the guide to integrating with Travis CI | ||||
onboarding.project_analysis.guide_to_integrate_vsts=follow the guide to integrating with VSTS | |||||
onboarding.project_analysis.guide_to_integrate_vsts=follow the guide to integrating with Azure DevOps Services | |||||
onboarding.project_analysis.simply_link=Simply {link}. | onboarding.project_analysis.simply_link=Simply {link}. | ||||
onboarding.project_analysis.suggestions.bitbucket=If you are using Bitbucket Cloud Pipelines, the SonarCloud App makes it easier to run these commands with your CI process. | onboarding.project_analysis.suggestions.bitbucket=If you are using Bitbucket Cloud Pipelines, the SonarCloud App makes it easier to run these commands with your CI process. | ||||
onboarding.project_analysis.suggestions.github=If you are using Travis CI, the SonarCloud Travis Add-on makes it easier to run these commands with your CI process. | onboarding.project_analysis.suggestions.github=If you are using Travis CI, the SonarCloud Travis Add-on makes it easier to run these commands with your CI process. |