diff --git a/.env b/.env index db6410f86e0..483f3748751 100644 --- a/.env +++ b/.env @@ -4,6 +4,7 @@ COMPOSE_PROJECT_NAME=sentry-self-hosted # See https://develop.sentry.dev/self-hosted/optional-features/errors-only/ COMPOSE_PROFILES=feature-complete SENTRY_EVENT_RETENTION_DAYS=90 +LAUNCHPAD_RPC_SHARED_SECRET=supersecret # You can either use a port number or an IP:PORT combo for SENTRY_BIND # See https://docs.docker.com/compose/compose-file/#ports for more SENTRY_BIND=9000 @@ -18,6 +19,7 @@ SYMBOLICATOR_IMAGE=ghcr.io/getsentry/symbolicator:nightly TASKBROKER_IMAGE=ghcr.io/getsentry/taskbroker:nightly VROOM_IMAGE=ghcr.io/getsentry/vroom:nightly UPTIME_CHECKER_IMAGE=ghcr.io/getsentry/uptime-checker:nightly +LAUNCHPAD_IMAGE=ghcr.io/getsentry/launchpad:nightly HEALTHCHECK_INTERVAL=30s HEALTHCHECK_TIMEOUT=1m30s HEALTHCHECK_RETRIES=10 diff --git a/.github/ISSUE_TEMPLATE/release.yml b/.github/ISSUE_TEMPLATE/release.yml index 11077ab41fe..13d31e431a3 100644 --- a/.github/ISSUE_TEMPLATE/release.yml +++ b/.github/ISSUE_TEMPLATE/release.yml @@ -17,6 +17,7 @@ body: - [ ] [`vroom`](https://github.com/getsentry/vroom/actions/workflows/release.yaml) - [ ] [`uptime-checker`](https://github.com/getsentry/uptime-checker/actions/workflows/release.yml) - [ ] [`taskbroker`](https://github.com/getsentry/taskbroker/actions/workflows/release.yml) + - [ ] [`launchpad`](https://github.com/getsentry/launchpad/actions/workflows/release.yml) - [ ] Release self-hosted. - [ ] [Prepare the `self-hosted` release](https://github.com/getsentry/self-hosted/actions/workflows/release.yml) (_replace with publish issue repo link_). - [ ] Check to make sure the new release branch in self-hosted includes the appropriate CalVer images. diff --git a/_integration-test/test_01_basics.py b/_integration-test/test_01_basics.py index a2073e2df11..f07ad82a43d 100644 --- a/_integration-test/test_01_basics.py +++ b/_integration-test/test_01_basics.py @@ -55,6 +55,19 @@ def get_sentry_dsn(client: httpx.Client) -> str: sentry_dsn = json.loads(response.text)[0]["dsn"]["public"] return sentry_dsn +@lru_cache +def get_organization_token(client: httpx.Client, csrf_token: str, name: str) -> str: + response = client.post( + f"{SENTRY_TEST_HOST}/api/0/organizations/sentry/org-auth-tokens/", + follow_redirects=True, + data={"name": name}, + headers={ + "Referer": f"{SENTRY_TEST_HOST}/settings/sentry/auth-tokens/new-token/", + "X-CSRFToken": csrf_token, + }, + ) + token = json.loads(response.text)["token"] + return token @pytest.fixture() def client_login(): @@ -76,7 +89,6 @@ def client_login(): assert login_response.status_code == 200 yield (client, login_response) - def test_initial_redirect(): initial_auth_redirect = httpx.get(SENTRY_TEST_HOST, follow_redirects=True) assert initial_auth_redirect.url == f"{SENTRY_TEST_HOST}/auth/login/sentry/" @@ -490,6 +502,31 @@ def test_receive_logs_events(client_login): lambda x: len(json.loads(x)["data"]) > 0, ) +@pytest.mark.skipif(os.environ.get("COMPOSE_PROFILES") != "feature-complete", reason="Only run if feature-complete") +def test_upload_mobile_builds(client_login): + client, login_response = client_login + sentry_dsn = get_sentry_dsn(client) + + organization_auth_token = get_organization_token(client, login_response.cookies["sc"], "preprod") + env = os.environ.copy() + env["SENTRY_DSN"] = sentry_dsn + subprocess.run( + ["sentry-cli", "--log-level", "DEBUG", "--url", SENTRY_TEST_HOST, "--auth-token", organization_auth_token, "build", "upload", "hn.aab", "--org", "sentry", "--project", "internal"], + check=True, + shell=False, + env=env, + cwd="_integration-test/emerge-tools", + stdout=sys.stdout, + stderr=sys.stderr, + timeout=60, + ) + + poll_for_response( + f"{SENTRY_TEST_HOST}/api/0/organizations/sentry/builds/?display=size&per_page=25&project=-1&query=%21size_state%3Anot_ran&statsPeriod=24h&tab=mobile-builds", + client, + lambda x: len(json.loads(x)) > 0, + ) + def test_customizations(): commands = [ [ diff --git a/action.yaml b/action.yaml index 601aaa13099..bc8592c3aac 100644 --- a/action.yaml +++ b/action.yaml @@ -215,12 +215,26 @@ runs: with: node-version: "22.x" + - name: Setup Sentry CLI + shell: bash + run: curl -sL https://sentry.io/get-cli/ | SENTRY_CLI_VERSION="3.3.5" bash + - name: Install Nodejs dependencies shell: bash run: | cd ${{ github.action_path }}/_integration-test/nodejs npm ci + - name: Setup required Emerge Tools files + if: inputs.compose_profiles == 'feature-complete' + shell: bash + run: | + set -euo pipefail + cd ${{ github.action_path }} + mkdir -p _integration-test/emerge-tools + cd _integration-test/emerge-tools + curl -LO https://github.com/getsentry/launchpad/raw/893ad23dcfd81d70edbb26ea217d9d18e2ba81da/tests/_fixtures/android/hn.aab + - name: Integration Test shell: bash env: diff --git a/docker-compose.yml b/docker-compose.yml index b5d768f8ca0..661f1b8df33 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -70,6 +70,7 @@ x-sentry-defaults: &sentry_defaults SENTRY_MAIL_HOST: SENTRY_MAX_EXTERNAL_SOURCEMAP_SIZE: SENTRY_SYSTEM_SECRET_KEY: + LAUNCHPAD_RPC_SHARED_SECRET: SENTRY_STATSD_ADDR: "${STATSD_ADDR:-}" volumes: - "sentry-data:/data" @@ -770,6 +771,29 @@ services: command: run taskworker --concurrency=$SENTRY_TASKWORKER_CONCURRENCY --rpc-host=taskbroker:50051 --health-check-file-path=/tmp/health.txt --max-child-task-count=10000 healthcheck: <<: *file_healthcheck_defaults + launchpad-taskworker: + <<: [*restart_policy, *pull_policy] + image: "$LAUNCHPAD_IMAGE" + command: "worker --verbose" + environment: + LAUNCHPAD_WORKER_RPC_HOST: "taskbroker:50051" + LAUNCHPAD_WORKER_CONCURRENCY: "${LAUNCHPAD_TASKWORKER_CONCURRENCY:-4}" + LAUNCHPAD_WORKER_HEALTH_CHECK_FILE_PATH: "/tmp/health.txt" + KAFKA_BOOTSTRAP_SERVERS: "kafka:9092" + SENTRY_BASE_URL: "http://web:9000" + LAUNCHPAD_RPC_SHARED_SECRET: + LAUNCHPAD_ENV: "self-hosted" + healthcheck: + <<: *file_healthcheck_defaults + depends_on: + kafka: + <<: *depends_on-healthy + taskbroker: + <<: *depends_on-default + web: + <<: *depends_on-healthy + profiles: + - feature-complete vroom: <<: [*restart_policy, *pull_policy] image: "$VROOM_IMAGE" diff --git a/install/setup-custom-ca-certificate.sh b/install/setup-custom-ca-certificate.sh index 581fee37b14..e5a458d46dd 100644 --- a/install/setup-custom-ca-certificate.sh +++ b/install/setup-custom-ca-certificate.sh @@ -59,7 +59,7 @@ if [[ "${SETUP_CUSTOM_CA_CERTIFICATE:-}" == "1" ]]; then # Pairs of service nickname and the env var that holds the image reference. # All of these are loaded from .env (via install/_lib.sh) before this script runs. - image_nicknames=(relay symbolicator snuba vroom taskbroker uptime-checker) + image_nicknames=(relay symbolicator snuba vroom taskbroker uptime-checker launchpad) image_names=( "${RELAY_IMAGE:-}" "${SYMBOLICATOR_IMAGE:-}" @@ -67,6 +67,7 @@ if [[ "${SETUP_CUSTOM_CA_CERTIFICATE:-}" == "1" ]]; then "${VROOM_IMAGE:-}" "${TASKBROKER_IMAGE:-}" "${UPTIME_CHECKER_IMAGE:-}" + "${LAUNCHPAD_IMAGE:-}" ) custom_ca_debug "Target services: ${image_nicknames[*]}" @@ -182,6 +183,14 @@ x-custom-ca-uptime-checker: &ca_uptime_checker source: ./certificates/.generated/uptime-checker/etc/ssl/certs target: /etc/ssl/certs +x-custom-ca-launchpad: &ca_launchpad + volumes: + - type: bind + read_only: true + source: ./certificates/.generated/launchpad/etc/ssl/certs + target: /etc/ssl/certs + + services: relay: <<: *ca_relay @@ -247,6 +256,8 @@ services: <<: *ca_taskbroker uptime-checker: <<: *ca_uptime_checker + launchpad-taskworker: + <<: *ca_launchpad YAML fi diff --git a/install/update-docker-images.sh b/install/update-docker-images.sh index 9e6cc230a33..34ddf484b6b 100644 --- a/install/update-docker-images.sh +++ b/install/update-docker-images.sh @@ -22,5 +22,6 @@ $CONTAINER_ENGINE pull ${RELAY_IMAGE} || true $CONTAINER_ENGINE pull ${TASKBROKER_IMAGE} || true $CONTAINER_ENGINE pull ${VROOM_IMAGE} || true $CONTAINER_ENGINE pull ${UPTIME_CHECKER_IMAGE} || true +$CONTAINER_ENGINE pull ${LAUNCHPAD_IMAGE} || true echo "${_endgroup}" diff --git a/sentry/sentry.conf.example.py b/sentry/sentry.conf.example.py index 3bdc3e1a19d..4e5b23af2c2 100644 --- a/sentry/sentry.conf.example.py +++ b/sentry/sentry.conf.example.py @@ -433,6 +433,10 @@ def get_internal_network(): "organizations:ourlogs-stats", "organizations:ourlogs-replay-ui", ) + # Emerge Tools (Size Analysis, Build Distribution, etc) related flags + + ( + "organizations:preprod-frontend-routes", + ) } )