From 03663ea3196f53629f8e0bb860584481759d8392 Mon Sep 17 00:00:00 2001 From: Innokentii Konstantinov Date: Wed, 28 Jun 2023 17:52:17 +0800 Subject: [PATCH 1/7] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75375d7a..a982eb61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## v1.3.3 ### Added From be4176b9477d78824379b787f106b8faf6fb637c Mon Sep 17 00:00:00 2001 From: Vadim Stepanov Date: Wed, 28 Jun 2023 15:53:48 +0100 Subject: [PATCH 2/7] Make `OrderedModel.save()` respect additional arguments (#2382) # What this PR does Make `OrderedModel.save()` respect additional arguments (e.g. `using`) ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not required) --- engine/apps/base/models/ordered_model.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/engine/apps/base/models/ordered_model.py b/engine/apps/base/models/ordered_model.py index b286520d..0fd980e2 100644 --- a/engine/apps/base/models/ordered_model.py +++ b/engine/apps/base/models/ordered_model.py @@ -69,9 +69,9 @@ class OrderedModel(models.Model): def save(self, *args, **kwargs) -> None: if self.order is None: - self._save_no_order_provided() + self._save_no_order_provided(*args, **kwargs) else: - super().save() + super().save(*args, **kwargs) @_retry(OperationalError) # retry on deadlock def delete(self, *args, **kwargs) -> None: @@ -81,7 +81,7 @@ class OrderedModel(models.Model): super().delete(*args, **kwargs) @_retry((IntegrityError, OperationalError)) # retry on duplicate order or deadlock - def _save_no_order_provided(self) -> None: + def _save_no_order_provided(self, *args, **kwargs) -> None: """ Save self to DB without an order provided (e.g on creation). Order is set to the next available order, or 0 if there are no other instances. @@ -97,7 +97,7 @@ class OrderedModel(models.Model): instances = self._lock_ordering_queryset() # lock ordering queryset to prevent reading inconsistent data max_order = max(instance.order for instance in instances) if instances else -1 self.order = max_order + 1 - super().save() + super().save(*args, **kwargs) @_retry(OperationalError) # retry on deadlock def to(self, order: int) -> None: From 3ebfd9c8b26c65585ad7b7e555e36cfeb413c7ed Mon Sep 17 00:00:00 2001 From: Vadim Stepanov Date: Thu, 29 Jun 2023 11:09:02 +0100 Subject: [PATCH 3/7] Remove outdated Slack functionality to create alerts (#2383) # What this PR does There's an outdated Slack handler that creates alerts when a file is shared in a channel. I can't remember why it was introduced in the first place, but I'm pretty sure that it's deprecated a long time ago, and this feature is not documented anywhere. The PR also removes `AlertReceiveChannel.integration_slack_channel_id` as it's no longer used. ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not required) --- ...ivechannel_integration_slack_channel_id.py | 19 ++++++++++ .../alerts/models/alert_receive_channel.py | 2 -- engine/apps/alerts/tests/test_alert_group.py | 6 ++-- engine/apps/slack/scenarios/scenario_step.py | 1 - .../scenarios/slack_channel_integration.py | 36 ------------------- engine/apps/slack/views.py | 2 -- 6 files changed, 22 insertions(+), 44 deletions(-) create mode 100644 engine/apps/alerts/migrations/0018_remove_alertreceivechannel_integration_slack_channel_id.py diff --git a/engine/apps/alerts/migrations/0018_remove_alertreceivechannel_integration_slack_channel_id.py b/engine/apps/alerts/migrations/0018_remove_alertreceivechannel_integration_slack_channel_id.py new file mode 100644 index 00000000..97be1856 --- /dev/null +++ b/engine/apps/alerts/migrations/0018_remove_alertreceivechannel_integration_slack_channel_id.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.19 on 2023-06-28 16:00 + +from django.db import migrations +import django_migration_linter as linter + + +class Migration(migrations.Migration): + + dependencies = [ + ('alerts', '0017_alertgroup_is_restricted'), + ] + + operations = [ + linter.IgnoreMigration(), # This field is deprecated a long time ago. + migrations.RemoveField( + model_name='alertreceivechannel', + name='integration_slack_channel_id', + ), + ] diff --git a/engine/apps/alerts/models/alert_receive_channel.py b/engine/apps/alerts/models/alert_receive_channel.py index 5d17e86f..42d6ce0b 100644 --- a/engine/apps/alerts/models/alert_receive_channel.py +++ b/engine/apps/alerts/models/alert_receive_channel.py @@ -160,8 +160,6 @@ class AlertReceiveChannel(IntegrationOptionsMixin, MaintainableObject): verbal_name = models.CharField(max_length=150, null=True, default=None) description_short = models.CharField(max_length=250, null=True, default=None) - integration_slack_channel_id = models.CharField(max_length=150, null=True, default=None) - is_finished_alerting_setup = models.BooleanField(default=False) # *_*_template fields are legacy way of storing templates diff --git a/engine/apps/alerts/tests/test_alert_group.py b/engine/apps/alerts/tests/test_alert_group.py index d673567c..87a23d84 100644 --- a/engine/apps/alerts/tests/test_alert_group.py +++ b/engine/apps/alerts/tests/test_alert_group.py @@ -14,7 +14,7 @@ def test_render_for_phone_call( make_alert, ): organization, _ = make_organization_with_slack_team_identity() - alert_receive_channel = make_alert_receive_channel(organization, integration_slack_channel_id="CWER1ASD") + alert_receive_channel = make_alert_receive_channel(organization) alert_group = make_alert_group(alert_receive_channel) SlackMessage.objects.create(channel_id="CWER1ASD", alert_group=alert_group) @@ -60,7 +60,7 @@ def test_delete( slack_channel = make_slack_channel(slack_team_identity, name="general", slack_id="CWER1ASD") user = make_user(organization=organization) - alert_receive_channel = make_alert_receive_channel(organization, integration_slack_channel_id="CWER1ASD") + alert_receive_channel = make_alert_receive_channel(organization) alert_group = make_alert_group(alert_receive_channel) SlackMessage.objects.create(channel_id="CWER1ASD", alert_group=alert_group) @@ -104,7 +104,7 @@ def test_alerts_count_gt( make_alert, ): organization = make_organization() - alert_receive_channel = make_alert_receive_channel(organization, integration_slack_channel_id="CWER1ASD") + alert_receive_channel = make_alert_receive_channel(organization) alert_group = make_alert_group(alert_receive_channel) diff --git a/engine/apps/slack/scenarios/scenario_step.py b/engine/apps/slack/scenarios/scenario_step.py index e6cd768f..38de8d0c 100644 --- a/engine/apps/slack/scenarios/scenario_step.py +++ b/engine/apps/slack/scenarios/scenario_step.py @@ -32,7 +32,6 @@ EVENT_SUBTYPE_MESSAGE_CHANGED = "message_changed" EVENT_SUBTYPE_MESSAGE_DELETED = "message_deleted" EVENT_SUBTYPE_BOT_MESSAGE = "bot_message" EVENT_SUBTYPE_THREAD_BROADCAST = "thread_broadcast" -EVENT_SUBTYPE_FILE_SHARE = "file_share" EVENT_TYPE_CHANNEL_DELETED = "channel_deleted" EVENT_TYPE_CHANNEL_CREATED = "channel_created" EVENT_TYPE_CHANNEL_RENAMED = "channel_rename" diff --git a/engine/apps/slack/scenarios/slack_channel_integration.py b/engine/apps/slack/scenarios/slack_channel_integration.py index 348b6209..8d5a0147 100644 --- a/engine/apps/slack/scenarios/slack_channel_integration.py +++ b/engine/apps/slack/scenarios/slack_channel_integration.py @@ -1,9 +1,7 @@ -import json import logging from django.apps import apps -from apps.integrations.tasks import create_alert from apps.slack.scenarios import scenario_step logger = logging.getLogger(__name__) @@ -30,9 +28,6 @@ class SlackChannelMessageEventStep(scenario_step.ScenarioStep): and "thread_ts" in payload["event"]["previous_message"] ): self.delete_thread_message_from_resolution_note(slack_user_identity, payload) - # Otherwise check if it is a message from channel with Slack Channel Integration - else: - self.create_alert_for_slack_channel_integration_if_needed(payload) def save_thread_message_for_resolution_note(self, slack_user_identity, payload): ResolutionNoteSlackMessage = apps.get_model("alerts", "ResolutionNoteSlackMessage") @@ -144,37 +139,6 @@ class SlackChannelMessageEventStep(scenario_step.ScenarioStep): slack_thread_message.delete() self.alert_group_slack_service.update_alert_group_slack_message(alert_group) - def create_alert_for_slack_channel_integration_if_needed(self, payload): - if "subtype" in payload["event"] and payload["event"]["subtype"] != scenario_step.EVENT_SUBTYPE_FILE_SHARE: - return - AlertReceiveChannel = apps.get_model("alerts", "AlertReceiveChannel") - alert_receive_channels = AlertReceiveChannel.objects.filter( - integration_slack_channel_id=payload["event"]["channel"], organization=self.organization - ).all() - for alert_receive_channel in alert_receive_channels: - r = self._slack_client.api_call( - "chat.getPermalink", - channel=payload["event"]["channel"], - message_ts=payload["event"]["ts"], - ) - # insert permalink to payload to have access to it in templaters - payload["event"]["amixr_mixin"] = {"permalink": r["permalink"]} - - create_alert.apply_async( - [], - { - "title": "<#{}>".format(payload["event"]["channel"]), - "message": "{}\n_New message in <#{}> channel_".format( - payload["event"]["text"], payload["event"]["channel"] - ), - "image_url": None, - "link_to_upstream_details": r["permalink"], - "alert_receive_channel_pk": alert_receive_channel.pk, - "integration_unique_data": json.dumps(payload["event"]), - "raw_request_data": payload["event"], - }, - ) - STEPS_ROUTING = [ { diff --git a/engine/apps/slack/views.py b/engine/apps/slack/views.py index 5b0616e7..9e6bc929 100644 --- a/engine/apps/slack/views.py +++ b/engine/apps/slack/views.py @@ -28,7 +28,6 @@ from apps.slack.scenarios.profile_update import STEPS_ROUTING as PROFILE_UPDATE_ from apps.slack.scenarios.resolution_note import STEPS_ROUTING as RESOLUTION_NOTE_ROUTING from apps.slack.scenarios.scenario_step import ( EVENT_SUBTYPE_BOT_MESSAGE, - EVENT_SUBTYPE_FILE_SHARE, EVENT_SUBTYPE_MESSAGE_CHANGED, EVENT_SUBTYPE_MESSAGE_DELETED, EVENT_TYPE_APP_MENTION, @@ -334,7 +333,6 @@ class SlackEventApiEndpointView(APIView): in [ EVENT_SUBTYPE_BOT_MESSAGE, EVENT_SUBTYPE_MESSAGE_CHANGED, - EVENT_SUBTYPE_FILE_SHARE, EVENT_SUBTYPE_MESSAGE_DELETED, ] ) From 60ef4450e61581420d88f8a7ce6456744446a279 Mon Sep 17 00:00:00 2001 From: Joey Orlando Date: Thu, 29 Jun 2023 12:48:23 +0200 Subject: [PATCH 4/7] in the e2e tests, await the grafana instance if it is currently down/unavailable (#2366) # What this PR does In the e2e tests, await the grafana instance if it is currently down/unavailable. This is mostly useful for when the tests are run against a hosted grafana instance and it is possible that the instance is paused ([example build](https://drone.grafana.net/grafana/oncall-private/5735/1/4)). https://www.loom.com/share/35eb49035d454ac6ba306cddfe63f255 ## Checklist - [ ] Unit, integration, and e2e (if applicable) tests updated (N/A) - [ ] Documentation added (or `pr:no public docs` PR label added if not required) (N/A) - [ ] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not required) (N/A) --- grafana-plugin/.gitignore | 2 +- .../integration-tests/globalSetup.ts | 65 ++++++++++++++----- grafana-plugin/playwright.config.ts | 17 ++++- 3 files changed, 65 insertions(+), 19 deletions(-) diff --git a/grafana-plugin/.gitignore b/grafana-plugin/.gitignore index 16f10cb1..43e7ea8a 100644 --- a/grafana-plugin/.gitignore +++ b/grafana-plugin/.gitignore @@ -19,4 +19,4 @@ frontend_enterprise /test-results/ /playwright-report/ /playwright/.cache/ -storageState.json +/integration-tests/storageState.json diff --git a/grafana-plugin/integration-tests/globalSetup.ts b/grafana-plugin/integration-tests/globalSetup.ts index 79fb4b0c..5881971a 100644 --- a/grafana-plugin/integration-tests/globalSetup.ts +++ b/grafana-plugin/integration-tests/globalSetup.ts @@ -1,20 +1,39 @@ -import { chromium, FullConfig, expect, Page } from '@playwright/test'; +import { test as setup, chromium, FullConfig, expect, Page, BrowserContext, APIResponse } from '@playwright/test'; import { BASE_URL, GRAFANA_PASSWORD, GRAFANA_USERNAME, IS_OPEN_SOURCE, ONCALL_API_URL } from './utils/constants'; import { clickButton, getInputByName } from './utils/forms'; import { goToGrafanaPage } from './utils/navigation'; +import { STORAGE_STATE } from '../playwright.config'; +const IS_CLOUD = !IS_OPEN_SOURCE; const GLOBAL_SETUP_RETRIES = 3; +const makeGrafanaLoginRequest = async (browserContext: BrowserContext): Promise => + browserContext.request.post(`${BASE_URL}/login`, { + data: { + user: GRAFANA_USERNAME, + password: GRAFANA_PASSWORD, + }, + }); + +const pollGrafanaInstanceUntilItIsHealthy = async (browserContext: BrowserContext): Promise => { + console.log('Polling the grafana instance to make sure it is healthy'); + + const res = await makeGrafanaLoginRequest(browserContext); + + if (!res.ok()) { + console.log(`Grafana instance is unavailable. Got HTTP ${res.status()}. Will wait 5 seconds and then try again`); + await new Promise((resolve) => setTimeout(resolve, 5000)); + return pollGrafanaInstanceUntilItIsHealthy(browserContext); + } + console.log('Grafana instance is available'); + return true; +}; + /** * go to config page and wait for plugin icon to be available on left-hand navigation */ const configureOnCallPlugin = async (page: Page): Promise => { - // plugin configuration can safely be skipped for non open-source environments - if (!IS_OPEN_SOURCE) { - return; - } - /** * go to the oncall plugin configuration page and wait for the page to be loaded */ @@ -52,19 +71,26 @@ const globalSetup = async (config: FullConfig): Promise => { const browser = await chromium.launch({ headless, slowMo: headless ? 0 : 100 }); const browserContext = await browser.newContext(); - const res = await browserContext.request.post(`${BASE_URL}/login`, { - data: { - user: GRAFANA_USERNAME, - password: GRAFANA_PASSWORD, - }, - }); + if (IS_CLOUD) { + /** + * check that the grafana instance is available. If HTTP 503 is returned it means the + * instance is currently unavailable. Poll until it is available + */ + await pollGrafanaInstanceUntilItIsHealthy(browserContext); + } + + const res = await makeGrafanaLoginRequest(browserContext); expect(res.ok()).toBeTruthy(); - await browserContext.storageState({ path: './storageState.json' }); + await browserContext.storageState({ path: STORAGE_STATE }); // make sure the plugin has been configured const page = await browserContext.newPage(); - await configureOnCallPlugin(page); + + if (IS_OPEN_SOURCE) { + // plugin configuration can safely be skipped for cloud environments + await configureOnCallPlugin(page); + } await browserContext.close(); }; @@ -88,4 +114,13 @@ const globalSetupWithRetries = async (config: FullConfig): Promise => { await globalSetup(config); }; -export default globalSetupWithRetries; +setup('Configure Grafana OnCall plugin', async ({}, { config }) => { + /** + * Unconditionally marks the setup as "slow", giving it triple the default timeout. + * This is mostly useful for the rare case for Cloud Grafana instances where the instance may be down/unavailable + * and we need to poll it until it is available + */ + setup.slow(); + + await globalSetupWithRetries(config); +}); diff --git a/grafana-plugin/playwright.config.ts b/grafana-plugin/playwright.config.ts index 5cae7ef8..8ea67ebc 100644 --- a/grafana-plugin/playwright.config.ts +++ b/grafana-plugin/playwright.config.ts @@ -1,3 +1,5 @@ +import path from 'path'; + import type { PlaywrightTestConfig } from '@playwright/test'; import { devices } from '@playwright/test'; @@ -7,12 +9,13 @@ import { devices } from '@playwright/test'; */ require('dotenv').config(); +export const STORAGE_STATE = path.join(__dirname, 'integration-tests/storageState.json'); + /** * See https://playwright.dev/docs/test-configuration. */ const config: PlaywrightTestConfig = { testDir: './integration-tests', - globalSetup: './integration-tests/globalSetup.ts', /* Maximum time one test can run for. */ timeout: 60 * 1000, expect: { @@ -38,8 +41,6 @@ const config: PlaywrightTestConfig = { reporter: 'html', /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { - storageState: './storageState.json', - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ actionTimeout: 0, /* Base URL to use in actions like `await page.goto('/')`. */ @@ -53,23 +54,33 @@ const config: PlaywrightTestConfig = { /* Configure projects for major browsers */ projects: [ + { + name: 'setup', + testMatch: /globalSetup\.ts/, + }, { name: 'chromium', use: { ...devices['Desktop Chrome'], + storageState: STORAGE_STATE, }, + dependencies: ['setup'], }, { name: 'firefox', use: { ...devices['Desktop Firefox'], + storageState: STORAGE_STATE, }, + dependencies: ['setup'], }, { name: 'webkit', use: { ...devices['Desktop Safari'], + storageState: STORAGE_STATE, }, + dependencies: ['setup'], }, /* Test against mobile viewports. */ From aefaa84f2865f81d7e187acd53dd5b371bdc667c Mon Sep 17 00:00:00 2001 From: Joey Orlando Date: Thu, 29 Jun 2023 12:49:00 +0200 Subject: [PATCH 5/7] update rabbitmq docker containers to v3.12.0 (#2359) # What this PR does Update `rabbitmq` Docker containers used in the `docker-compose` config files, Drone pipelines, and GitHub Actions to use version 3.12.0. FWIW, we're already using v12.0.0 of the bitnami `rabbitmq` `helm` chart which, by default, uses the `3.12.0-debian-11-r0` tag for the `rabbitmq` image ([chart docs](https://artifacthub.io/packages/helm/bitnami/rabbitmq/12.0.0)). closes #695 ## Checklist - [ ] Unit, integration, and e2e (if applicable) tests updated (N/A) - [ ] Documentation added (or `pr:no public docs` PR label added if not required) (N/A) - [ ] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not required) (N/A) --- .drone.yml | 4 ++-- .github/workflows/linting-and-tests.yml | 6 +++--- docker-compose-developer.yml | 2 +- docker-compose-mysql-rabbitmq.yml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.drone.yml b/.drone.yml index 6691a82a..05b51ece 100644 --- a/.drone.yml +++ b/.drone.yml @@ -144,7 +144,7 @@ steps: # Services for Unit Test Backend services: - name: rabbit_test - image: rabbitmq:3.7.19 + image: rabbitmq:3.12.0 environment: RABBITMQ_DEFAULT_USER: rabbitmq RABBITMQ_DEFAULT_PASS: rabbitmq @@ -418,6 +418,6 @@ kind: secret name: drone_token --- kind: signature -hmac: 59ad498428731001484be9ac6b9d10685b2cd49f30eb3d97ed7dc99f031dca22 +hmac: e4d25ad9f26d0a2444033ec077029da50818d912fd24ba49c0a915947adffbab ... diff --git a/.github/workflows/linting-and-tests.yml b/.github/workflows/linting-and-tests.yml index 0cf29768..ded42414 100644 --- a/.github/workflows/linting-and-tests.yml +++ b/.github/workflows/linting-and-tests.yml @@ -96,7 +96,7 @@ jobs: SLACK_CLIENT_OAUTH_ID: 1 services: rabbit_test: - image: rabbitmq:3.7.19 + image: rabbitmq:3.12.0 env: RABBITMQ_DEFAULT_USER: rabbitmq RABBITMQ_DEFAULT_PASS: rabbitmq @@ -148,7 +148,7 @@ jobs: ONCALL_TESTING_RBAC_ENABLED: ${{ matrix.rbac_enabled }} services: rabbit_test: - image: rabbitmq:3.7.19 + image: rabbitmq:3.12.0 env: RABBITMQ_DEFAULT_USER: rabbitmq RABBITMQ_DEFAULT_PASS: rabbitmq @@ -192,7 +192,7 @@ jobs: ONCALL_TESTING_RBAC_ENABLED: ${{ matrix.rbac_enabled }} services: rabbit_test: - image: rabbitmq:3.7.19 + image: rabbitmq:3.12.0 env: RABBITMQ_DEFAULT_USER: rabbitmq RABBITMQ_DEFAULT_PASS: rabbitmq diff --git a/docker-compose-developer.yml b/docker-compose-developer.yml index c44633e4..a7bc8910 100644 --- a/docker-compose-developer.yml +++ b/docker-compose-developer.yml @@ -179,7 +179,7 @@ services: rabbitmq: container_name: rabbitmq labels: *oncall-labels - image: "rabbitmq:3.7.15-management" + image: "rabbitmq:3.12.0-management" restart: always environment: RABBITMQ_DEFAULT_USER: "rabbitmq" diff --git a/docker-compose-mysql-rabbitmq.yml b/docker-compose-mysql-rabbitmq.yml index f116415e..0fee8cb6 100644 --- a/docker-compose-mysql-rabbitmq.yml +++ b/docker-compose-mysql-rabbitmq.yml @@ -99,7 +99,7 @@ services: cpus: "0.1" rabbitmq: - image: "rabbitmq:3.7.15-management" + image: "rabbitmq:3.12.0-management" restart: always hostname: rabbitmq volumes: From d2754ae64f6b470ab4bb9ea6500ada2b97494959 Mon Sep 17 00:00:00 2001 From: Joey Orlando Date: Thu, 29 Jun 2023 12:51:21 +0200 Subject: [PATCH 6/7] use docker buildx native multiarch image support (#2375) # What this PR does `docker buildx` natively supports multiarch builds. This means we no longer need to have duplicate `docker build` Drone steps + there is no longer a need for the manual "manifesting" step. This [blog post](https://www.docker.com/blog/multi-arch-build-and-images-the-simple-way/) from Docker perfectly summarizes the difference between what we do now vs. what this PR would do. This would also get rid of pushing `vX.Y.Z-{architecture}` tagged images. These are redundant because modern `docker` clients can pull the appropriate image for the host OS, from a multiarch image: Screenshot 2023-06-28 at 12 54 09 ## Checklist - [ ] Unit, integration, and e2e (if applicable) tests updated (N/A) - [ ] Documentation added (or `pr:no public docs` PR label added if not required) (N/A) - [ ] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not required) (N/A) --- .drone.yml | 95 +++--------------------------------------------------- 1 file changed, 5 insertions(+), 90 deletions(-) diff --git a/.drone.yml b/.drone.yml index 05b51ece..91b4bd0c 100644 --- a/.drone.yml +++ b/.drone.yml @@ -224,10 +224,8 @@ trigger: --- kind: pipeline type: docker -name: OSS engine release (amd64) -platform: - os: linux - arch: amd64 +name: OSS engine release + steps: - name: set engine version image: alpine @@ -244,7 +242,8 @@ steps: DOCKER_BUILDKIT: 1 settings: repo: grafana/oncall - tags: ${DRONE_TAG}-amd64-linux + tags: ${DRONE_TAG} + platform: linux/arm64/v8,linux/amd64 dockerfile: engine/Dockerfile target: prod context: engine/ @@ -263,90 +262,6 @@ trigger: ref: - refs/tags/v*.*.* ---- -kind: pipeline -type: docker -name: OSS engine release (arm64) -platform: - os: linux - arch: arm64 -steps: - - name: set engine version - image: alpine - commands: - - apk add --no-cache bash sed - - if [ -z "$DRONE_TAG" ]; then echo "No tag, not modifying version"; else sed "0,/VERSION.*/ s/VERSION.*/VERSION = \"${DRONE_TAG}\"/g" engine/settings/base.py > engine/settings/base.temp && mv engine/settings/base.temp engine/settings/base.py; fi - - cat engine/settings/base.py | grep VERSION | head -1 - - - name: build and push docker image - image: plugins/docker - environment: - # force docker to use buildkit feature, this will skip build stages that aren't required in the final image (ie. dev & dev-enterprise) - # https://github.com/docker/cli/issues/1134#issuecomment-406449342 - DOCKER_BUILDKIT: 1 - settings: - repo: grafana/oncall - tags: ${DRONE_TAG}-arm64-linux - dockerfile: engine/Dockerfile - target: prod - context: engine/ - password: - from_secret: docker_password - username: - from_secret: docker_username - depends_on: - - set engine version - -trigger: - event: - - promote - target: - - oss - ref: - - refs/tags/v*.*.* - ---- -depends_on: - - OSS engine release (amd64) - - OSS engine release (arm64) -kind: pipeline -type: docker -name: manifest -steps: - - name: manifest tag - image: plugins/manifest - settings: - username: - from_secret: docker_username - password: - from_secret: docker_password - target: "grafana/oncall:${DRONE_TAG}" - template: "grafana/oncall:${DRONE_TAG}-ARCH-OS" - platforms: - - linux/amd64 - - linux/arm64 - - - name: manifest latest - image: plugins/manifest - settings: - username: - from_secret: docker_username - password: - from_secret: docker_password - target: "grafana/oncall:latest" - template: "grafana/oncall:${DRONE_TAG}-ARCH-OS" - platforms: - - linux/amd64 - - linux/arm64 - -trigger: - event: - - promote - target: - - oss - ref: - - refs/tags/v*.*.* - --- # Secret for pulling docker images. kind: secret @@ -418,6 +333,6 @@ kind: secret name: drone_token --- kind: signature -hmac: e4d25ad9f26d0a2444033ec077029da50818d912fd24ba49c0a915947adffbab +hmac: 610fb051f4361baa2621f6aa41c18b3afee5160492b30f5a5f23fcecf86f1b0c ... From 8ff5af5e4aaca76f5dc187b645058946935dfebd Mon Sep 17 00:00:00 2001 From: Joey Orlando Date: Thu, 29 Jun 2023 13:01:59 +0200 Subject: [PATCH 7/7] update CHANGELOG --- CHANGELOG.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a982eb61..53f4bbed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +5,19 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v1.3.3 +## Unreleased + +## v1.3.4 (2023-06-29) + +This version contains just some small cleanup and CI changes 🙂 + +## v1.3.3 (2023-06-28) ### Added - Add metric "how many alert groups user was notified of" to Prometheus exporter ([#2334](https://github.com/grafana/oncall/pull/2334/)) -## v1.3.2 +## v1.3.2 (2023-06-28) ### Changed