name: Dogfood merge | |||||
on: | |||||
push: | |||||
branches: | |||||
- master | |||||
- "dogfood/**" | |||||
jobs: | |||||
dogfood_merge: | |||||
# prevent job to run on public repository sonarsource/sonarqube | |||||
if: github.repository == 'sonarsource/sonar-enterprise' | |||||
runs-on: ubuntu-latest | |||||
name: Update dogfood-on-next branch | |||||
steps: | |||||
- name: Merge dogfood and master branches | |||||
uses: SonarSource/gh-action_dogfood_merge@v1 | |||||
env: | |||||
GITHUB_TOKEN: ${{ secrets.GITHUB_ORG_TOKEN }} | |||||
with: | |||||
dogfood-branch: "dogfood-on-next" | |||||
- name: Notify failures on Slack | |||||
if: failure() | |||||
uses: Ilshidur/action-slack@2.0.0 | |||||
env: | |||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} | |||||
with: | |||||
args: "Failed to merge dogfood and master branches, see the logs at https://github.com/SonarSource/sonar-enterprise/actions" |
name: Nightly QA | |||||
on: | |||||
schedule: | |||||
# at 1:30 daily | |||||
- cron: "30 1 * * *" | |||||
jobs: | |||||
nightly: | |||||
# prevent job to run on public repository sonarsource/sonarqube | |||||
if: github.repository == 'sonarsource/sonar-enterprise' | |||||
runs-on: ubuntu-latest | |||||
name: Trigger the nightly QA build | |||||
steps: | |||||
- name: Fetch code | |||||
uses: actions/checkout@v2 | |||||
with: | |||||
token: ${{ secrets.GITHUB_ORG_TOKEN }} | |||||
ref: branch-nightly-build | |||||
path: repo | |||||
- name: Trigger nightly build | |||||
run: | | |||||
cd repo/ | |||||
./private/trigger-nightly-build.sh | |||||
- name: Notify failures on Slack | |||||
if: failure() | |||||
uses: Ilshidur/action-slack@2.0.0 | |||||
env: | |||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} | |||||
with: | |||||
args: "Nightly QA failed, see the logs at https://github.com/SonarSource/sonar-enterprise/actions" |
name: Release | |||||
# This workflow is triggered when publishing a GitHub release | |||||
on: | |||||
release: | |||||
types: | |||||
- published | |||||
env: | |||||
PYTHONUNBUFFERED: 1 | |||||
jobs: | |||||
release: | |||||
if: github.repository == 'sonarsource/sonar-enterprise' | |||||
runs-on: ubuntu-latest | |||||
name: Start release process | |||||
timeout-minutes: 60 | |||||
steps: | |||||
- name: Run release action | |||||
id: run_release | |||||
uses: SonarSource/gh-action_LT_release@v2 | |||||
with: | |||||
distribute: true | |||||
publish_to_binaries: true | |||||
attach_artifacts_to_github_release: false | |||||
run_rules_cov: false | |||||
slack_channel: sonarqube-build | |||||
env: | |||||
ARTIFACTORY_API_KEY: ${{ secrets.ARTIFACTORY_API_KEY }} | |||||
BINTRAY_USER: ${{ secrets.BINTRAY_USER }} | |||||
BINTRAY_TOKEN: ${{ secrets.BINTRAY_TOKEN }} | |||||
BURGRX_USER: ${{ secrets.BURGRX_USER }} | |||||
BURGRX_PASSWORD: ${{ secrets.BURGRX_PASSWORD }} | |||||
CENTRAL_USER: ${{ secrets.CENTRAL_USER }} | |||||
CENTRAL_PASSWORD: ${{ secrets.CENTRAL_PASSWORD }} | |||||
CIRRUS_TOKEN: ${{ secrets.CIRRUS_TOKEN }} | |||||
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} | |||||
PATH_PREFIX: ${{ secrets.BINARIES_PATH_PREFIX }} | |||||
GITHUB_TOKEN: ${{ secrets.RELEASE_GITHUB_TOKEN }} | |||||
RELEASE_SSH_USER: ${{ secrets.RELEASE_SSH_USER }} | |||||
RELEASE_SSH_KEY: ${{ secrets.RELEASE_SSH_KEY }} | |||||
SLACK_API_TOKEN: ${{secrets.SLACK_API_TOKEN }} | |||||
- name: Log outputs | |||||
if: always() | |||||
run: | | |||||
echo "${{ steps.run_release.outputs.releasability }}" | |||||
echo "${{ steps.run_release.outputs.release }}" | |||||
echo "${{ steps.run_release.outputs.distribute_release }}" | |||||
- name: Notify success on Slack | |||||
uses: Ilshidur/action-slack@2.0.0 | |||||
env: | |||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} | |||||
with: | |||||
args: "Release successful for {{ GITHUB_REPOSITORY }} by {{ GITHUB_ACTOR }}" | |||||
- name: Notify failures on Slack | |||||
uses: Ilshidur/action-slack@2.0.0 | |||||
if: failure() | |||||
env: | |||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} | |||||
with: | |||||
args: "Release failed, see the logs at https://github.com/{{ GITHUB_REPOSITORY }}/actions by {{ GITHUB_ACTOR }}" |
name: Suggest dependency upgrades | |||||
on: | |||||
# use push to test the bot | |||||
# push: | |||||
# branches-ignore: | |||||
# - 'bot/upgrade_plugins**' | |||||
schedule: | |||||
# at 5:00 every Monday | |||||
- cron: '0 5 * * MON' | |||||
jobs: | |||||
suggest-upgrades-job: | |||||
# prevent job to run on public repository sonarsource/sonarqube (on which GitHub Actions are disabled) | |||||
if: github.repository == 'sonarsource/sonar-enterprise' | |||||
runs-on: ubuntu-latest | |||||
name: List available upgrades | |||||
steps: | |||||
- uses: actions/checkout@v2 | |||||
with: | |||||
fetch-depth: 1 | |||||
ref: master | |||||
- name: Set up JDK | |||||
uses: actions/setup-java@v1 | |||||
with: | |||||
java-version: 11 | |||||
- name: Cache Gradle Wrapper | |||||
uses: actions/cache@v1 | |||||
with: | |||||
path: ~/.gradle/wrapper | |||||
key: ${{ runner.os }}-gradlew-${{ hashFiles('**/*.zip') }} | |||||
restore-keys: ${{ runner.os }}-gradlew | |||||
- name: Find upgrades | |||||
env: | |||||
ARTIFACTORY_PRIVATE_USERNAME: ${{ secrets.REPOX_LOGIN }} | |||||
ARTIFACTORY_PRIVATE_PASSWORD: ${{ secrets.REPOX_API_KEY }} | |||||
run: | | |||||
./gradlew dependencyUpdates yarn_audit -Drevision=release |
name: Sync LTS branch | |||||
on: | |||||
schedule: | |||||
# at 20:00 daily | |||||
- cron: "0 20 * * *" | |||||
jobs: | |||||
sync_lts: | |||||
# prevent job to run on public repository sonarsource/sonarqube | |||||
if: github.repository == 'sonarsource/sonar-enterprise' | |||||
runs-on: ubuntu-latest | |||||
name: Sync LTS branch of sonarsource/sonar-enterprise with sonarsource/sonarqube | |||||
steps: | |||||
- name: Fetch code | |||||
uses: actions/checkout@v2 | |||||
with: | |||||
token: ${{ secrets.GITHUB_ORG_TOKEN }} | |||||
ref: master | |||||
path: repo | |||||
- name: Sync LTS branch | |||||
run: ./repo/private/sync-public-git-branches.sh | |||||
env: | |||||
GITHUB_ORG_TOKEN: ${{ secrets.GITHUB_ORG_TOKEN }} | |||||
BRANCH_NAME: branch-7.9 | |||||
- name: Notify failures on Slack | |||||
if: failure() | |||||
uses: Ilshidur/action-slack@2.0.0 | |||||
env: | |||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} | |||||
with: | |||||
args: "Nightly public sync failed, see the logs at https://github.com/SonarSource/sonar-enterprise/actions" |
name: Sync master branch | |||||
on: | |||||
schedule: | |||||
# at 20:00 daily | |||||
- cron: "0 20 * * *" | |||||
jobs: | |||||
sync_master: | |||||
# prevent job to run on public repository sonarsource/sonarqube | |||||
if: github.repository == 'sonarsource/sonar-enterprise' | |||||
runs-on: ubuntu-latest | |||||
name: Sync master branch of sonarsource/sonar-enterprise with sonarsource/sonarqube | |||||
steps: | |||||
- name: Fetch code | |||||
uses: actions/checkout@v2 | |||||
with: | |||||
token: ${{ secrets.GITHUB_ORG_TOKEN }} | |||||
ref: master | |||||
path: repo | |||||
- name: Sync master branch | |||||
run: ./repo/private/sync-public-git-branches.sh | |||||
env: | |||||
GITHUB_ORG_TOKEN: ${{ secrets.GITHUB_ORG_TOKEN }} | |||||
BRANCH_NAME: master | |||||
- name: Notify failures on Slack | |||||
if: failure() | |||||
uses: Ilshidur/action-slack@2.0.0 | |||||
env: | |||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} | |||||
with: | |||||
args: "Nightly public sync failed, see the logs at https://github.com/SonarSource/sonar-enterprise/actions" |
import static org.sonar.scanner.scan.branch.BranchType.PULL_REQUEST; | import static org.sonar.scanner.scan.branch.BranchType.PULL_REQUEST; | ||||
public class ReportPublisher implements Startable { | public class ReportPublisher implements Startable { | ||||
private static final int DEFAULT_WRITE_TIMEOUT = 30_000; | |||||
private static final Logger LOG = Loggers.get(ReportPublisher.class); | private static final Logger LOG = Loggers.get(ReportPublisher.class); | ||||
private static final String CHARACTERISTIC = "characteristic"; | private static final String CHARACTERISTIC = "characteristic"; | ||||
private static final String DASHBOARD = "dashboard"; | private static final String DASHBOARD = "dashboard"; | ||||
WsResponse response; | WsResponse response; | ||||
try { | try { | ||||
post.setWriteTimeOutInMs(DEFAULT_WRITE_TIMEOUT); | |||||
response = wsClient.call(post).failIfNotSuccessful(); | response = wsClient.call(post).failIfNotSuccessful(); | ||||
} catch (HttpException e) { | } catch (HttpException e) { | ||||
throw MessageException.of(String.format("Failed to upload report - %s", DefaultScannerWsClient.createErrorMessage(e))); | throw MessageException.of(String.format("Failed to upload report - %s", DefaultScannerWsClient.createErrorMessage(e))); |
import static org.apache.commons.io.FileUtils.readFileToString; | import static org.apache.commons.io.FileUtils.readFileToString; | ||||
import static org.assertj.core.api.Assertions.assertThat; | import static org.assertj.core.api.Assertions.assertThat; | ||||
import static org.mockito.ArgumentMatchers.any; | import static org.mockito.ArgumentMatchers.any; | ||||
import static org.mockito.ArgumentMatchers.argThat; | |||||
import static org.mockito.Mockito.mock; | import static org.mockito.Mockito.mock; | ||||
import static org.mockito.Mockito.verify; | import static org.mockito.Mockito.verify; | ||||
import static org.mockito.Mockito.when; | import static org.mockito.Mockito.when; | ||||
.resolve("report-task.txt")); | .resolve("report-task.txt")); | ||||
} | } | ||||
@Test | |||||
public void use_30s_write_timeout() { | |||||
MockWsResponse submitMockResponse = new MockWsResponse(); | |||||
submitMockResponse.setContent(Ce.SubmitResponse.newBuilder().setTaskId("task-1234").build().toByteArray()); | |||||
when(wsClient.call(any())).thenReturn(submitMockResponse); | |||||
underTest.start(); | |||||
underTest.execute(); | |||||
verify(wsClient).call(argThat(req -> req.getWriteTimeOutInMs().orElse(0) == 30_000)); | |||||
} | |||||
@Test | @Test | ||||
public void dump_information_about_report_uploading() throws IOException { | public void dump_information_about_report_uploading() throws IOException { | ||||
underTest.prepareAndDumpMetadata("TASK-123"); | underTest.prepareAndDumpMetadata("TASK-123"); |
private final DefaultParameters parameters = new DefaultParameters(); | private final DefaultParameters parameters = new DefaultParameters(); | ||||
private final DefaultHeaders headers = new DefaultHeaders(); | private final DefaultHeaders headers = new DefaultHeaders(); | ||||
private OptionalInt timeOutInMs = OptionalInt.empty(); | private OptionalInt timeOutInMs = OptionalInt.empty(); | ||||
private OptionalInt writeTimeOutInMs = OptionalInt.empty(); | |||||
BaseRequest(String path) { | BaseRequest(String path) { | ||||
this.path = path; | this.path = path; | ||||
} | } | ||||
return (SELF) this; | return (SELF) this; | ||||
} | } | ||||
@Override | |||||
public OptionalInt getWriteTimeOutInMs() { | |||||
return writeTimeOutInMs; | |||||
} | |||||
public SELF setWriteTimeOutInMs(int writeTimeOutInMs) { | |||||
this.writeTimeOutInMs = OptionalInt.of(writeTimeOutInMs); | |||||
return (SELF) this; | |||||
} | |||||
/** | /** | ||||
* Expected media type of response. Default is {@link MediaTypes#JSON}. | * Expected media type of response. Default is {@link MediaTypes#JSON}. | ||||
*/ | */ |
.newBuilder(); | .newBuilder(); | ||||
} | } | ||||
private static OkHttpClient prepareOkHttpClient(OkHttpClient okHttpClient, WsRequest wsRequest) { | |||||
if (!wsRequest.getTimeOutInMs().isPresent()) { | |||||
static OkHttpClient prepareOkHttpClient(OkHttpClient okHttpClient, WsRequest wsRequest) { | |||||
if (!wsRequest.getTimeOutInMs().isPresent() && !wsRequest.getWriteTimeOutInMs().isPresent()) { | |||||
return okHttpClient; | return okHttpClient; | ||||
} | } | ||||
OkHttpClient.Builder builder = okHttpClient.newBuilder(); | |||||
if (wsRequest.getTimeOutInMs().isPresent()) { | |||||
builder.readTimeout(wsRequest.getTimeOutInMs().getAsInt(), TimeUnit.MILLISECONDS); | |||||
} | |||||
if (wsRequest.getWriteTimeOutInMs().isPresent()) { | |||||
builder.writeTimeout(wsRequest.getWriteTimeOutInMs().getAsInt(), TimeUnit.MILLISECONDS); | |||||
} | |||||
return okHttpClient.newBuilder() | |||||
.readTimeout(wsRequest.getTimeOutInMs().getAsInt(), TimeUnit.MILLISECONDS) | |||||
.build(); | |||||
return builder.build(); | |||||
} | } | ||||
private static void completeUrlQueryParameters(BaseRequest<?> request, HttpUrl.Builder urlBuilder) { | private static void completeUrlQueryParameters(BaseRequest<?> request, HttpUrl.Builder urlBuilder) { | ||||
try { | try { | ||||
return call.execute(); | return call.execute(); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new IllegalStateException("Fail to request " + okRequest.url(), e); | |||||
throw new IllegalStateException("Fail to request url: " + okRequest.url(), e); | |||||
} | } | ||||
} | } | ||||
OptionalInt getTimeOutInMs(); | OptionalInt getTimeOutInMs(); | ||||
OptionalInt getWriteTimeOutInMs(); | |||||
/** | /** | ||||
* | * | ||||
* In case of multi value parameters, returns the first value | * In case of multi value parameters, returns the first value |
assertThat(underTest.getParams()).isEmpty(); | assertThat(underTest.getParams()).isEmpty(); | ||||
assertThat(underTest.getMediaType()).isEqualTo(MediaTypes.JSON); | assertThat(underTest.getMediaType()).isEqualTo(MediaTypes.JSON); | ||||
assertThat(underTest.getPath()).isEqualTo("api/foo"); | assertThat(underTest.getPath()).isEqualTo("api/foo"); | ||||
assertThat(underTest.getWriteTimeOutInMs()).isEmpty(); | |||||
} | |||||
@Test | |||||
public void set_write_timeout() { | |||||
underTest.setWriteTimeOutInMs(30_000); | |||||
assertThat(underTest.getWriteTimeOutInMs()).hasValue(30_000); | |||||
} | } | ||||
@Test | @Test |
import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||
import javax.net.ssl.SSLSocketFactory; | import javax.net.ssl.SSLSocketFactory; | ||||
import okhttp3.ConnectionSpec; | import okhttp3.ConnectionSpec; | ||||
import okhttp3.OkHttpClient; | |||||
import okhttp3.mockwebserver.MockResponse; | import okhttp3.mockwebserver.MockResponse; | ||||
import okhttp3.mockwebserver.MockWebServer; | import okhttp3.mockwebserver.MockWebServer; | ||||
import okhttp3.mockwebserver.RecordedRequest; | import okhttp3.mockwebserver.RecordedRequest; | ||||
assertThat(underTest.okHttpClient().connectTimeoutMillis()).isEqualTo(74); | assertThat(underTest.okHttpClient().connectTimeoutMillis()).isEqualTo(74); | ||||
} | } | ||||
@Test | |||||
public void override_timeouts_with_request() { | |||||
OkHttpClient client = new OkHttpClient.Builder().build(); | |||||
WsRequest request = new PostRequest("abc").setWriteTimeOutInMs(123).setTimeOutInMs(234); | |||||
client = underTest.prepareOkHttpClient(client, request); | |||||
assertThat(client.writeTimeoutMillis()).isEqualTo(123); | |||||
assertThat(client.readTimeoutMillis()).isEqualTo(234); | |||||
} | |||||
@Test | @Test | ||||
public void send_user_agent() throws Exception { | public void send_user_agent() throws Exception { | ||||
answerHelloWorld(); | answerHelloWorld(); |