Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add slack message API to send message on slack #23030

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/actions/slack/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Send a slack message
author: Mozilla
description: Send a slack message to a channel.

inputs:
slack_channel_id:
description: >-
The Slack channel id to send notification to.
To find the channel id, go to the channel settings and copy the channel id from the URL.
required: true
message:
description: The message to send to Slack.
required: true

runs:
using: composite
steps:
- name: send slack message
uses: slackapi/slack-github-action@v1
with:
channel-id: ${{ inputs.slack_channel_id }}
slack-message: >-
workflow: ${{ github.workflow_url }}
================================
${{ inputs.message }}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
15 changes: 15 additions & 0 deletions .github/workflows/health_check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Health Check

on:
workflow_dispatch:
pull_request:

jobs:
health_check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/slack
with:
slack_channel_id: ${{ secrets.SLACK_CHANNEL_REMORA }}
message: "Hello, world!"
48 changes: 25 additions & 23 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,24 @@ ENV BUILD_INFO=/build-info.json
SHELL ["/bin/bash", "-xue", "-c"]

ENV OLYMPIA_UID=9500
# give olympia access to the HOME directory
ENV HOME=/data/olympia
ENV DEPS_DIR=${HOME}/deps
ENV NPM_DEPS_DIR=${HOME}/node_modules

RUN <<EOF
groupadd -g ${OLYMPIA_UID} olympia
useradd -u ${OLYMPIA_UID} -g ${OLYMPIA_UID} -s /sbin/nologin -d /data/olympia olympia
useradd -u ${OLYMPIA_UID} -g ${OLYMPIA_UID} -s /sbin/nologin -d ${HOME} olympia

# Create and chown olympia directories
olympia_dirs=("${DEPS_DIR}" "${NPM_DEPS_DIR}" "${HOME}/storage")
for dir in "${olympia_dirs[@]}"; do
mkdir -p ${dir}
chown -R olympia:olympia ${dir}
done
EOF

# give olympia access to the HOME directory
ENV HOME=/data/olympia

WORKDIR ${HOME}
RUN chown -R olympia:olympia ${HOME}

Expand Down Expand Up @@ -74,37 +85,28 @@ ENV LANG=en_US.UTF-8
ENV LC_ALL=en_US.UTF-8

RUN <<EOF
# Create directory for dependencies
mkdir /deps
chown -R olympia:olympia /deps


# For backwards-compatibility purposes, set up links to uwsgi. Note that
# the target does not exist yet at this point, but it will later.
ln -s /deps/bin/uwsgi /usr/bin/uwsgi
ln -s ${DEPS_DIR}/bin/uwsgi /usr/bin/uwsgi
ln -s /usr/bin/uwsgi /usr/sbin/uwsgi

# Create the storage directory and the test file to verify nginx routing
mkdir -p ${HOME}/storage
chown -R olympia:olympia ${HOME}/storage
EOF

USER olympia:olympia

ENV PIP_USER=true
ENV PIP_BUILD=/deps/build/
ENV PIP_CACHE_DIR=/deps/cache/
ENV PIP_SRC=/deps/src/
ENV PYTHONUSERBASE=/deps
ENV PIP_BUILD=${DEPS_DIR}/build/
ENV PIP_CACHE_DIR=${DEPS_DIR}/cache/
ENV PIP_SRC=${DEPS_DIR}/src/
ENV PYTHONUSERBASE=${DEPS_DIR}
ENV PATH=$PYTHONUSERBASE/bin:$PATH
ENV NPM_CONFIG_PREFIX=/deps/
ENV NPM_CACHE_DIR=/deps/cache/npm
ENV NPM_CACHE_DIR=${DEPS_DIR}/cache/npm
ENV NPM_DEBUG=true
# Set python path to the project root and src to resolve olympia modules correctly
ENV PYTHONPATH=${HOME}:${HOME}/src

ENV PIP_COMMAND="python3 -m pip"
ENV NPM_ARGS="--prefix ${NPM_CONFIG_PREFIX} --cache ${NPM_CACHE_DIR} --loglevel verbose"
ENV NPM_ARGS="--cache ${NPM_CACHE_DIR} --loglevel verbose"

# All we need in "base" is pip to be installed
#this let's other layers install packages using the correct version.
Expand All @@ -127,16 +129,16 @@ COPY docker/etc/mime.types /etc/mime.types

# Define production dependencies as a single layer
# let's the rest of the stages inherit prod dependencies
# and makes copying the /deps dir to the final layer easy.
# and makes copying the /data/olympia/deps dir to the final layer easy.
FROM base AS pip_production

RUN \
--mount=type=bind,source=scripts/install_deps.py,target=${HOME}/scripts/install_deps.py \
# Files required to install pip dependencies
--mount=type=bind,source=./requirements/prod.txt,target=${HOME}/requirements/prod.txt \
# Files required to install npm dependencies
--mount=type=bind,source=package.json,target=/deps/package.json \
--mount=type=bind,source=package-lock.json,target=/deps/package-lock.json \
--mount=type=bind,source=package.json,target=${HOME}/package.json \
--mount=type=bind,source=package-lock.json,target=${HOME}/package-lock.json \
# Mounts for caching dependencies
--mount=type=cache,target=${PIP_CACHE_DIR},uid=${OLYMPIA_UID},gid=${OLYMPIA_UID} \
--mount=type=cache,target=${NPM_CACHE_DIR},uid=${OLYMPIA_UID},gid=${OLYMPIA_UID} \
Expand Down Expand Up @@ -197,4 +199,4 @@ COPY --from=info ${BUILD_INFO} ${BUILD_INFO}
# Copy compiled locales from builder
COPY --from=locales --chown=olympia:olympia ${HOME}/locale ${HOME}/locale
# Copy dependencies from `pip_production`
COPY --from=pip_production --chown=olympia:olympia /deps /deps
COPY --from=pip_production --chown=olympia:olympia ${DEPS_DIR} ${DEPS_DIR}
18 changes: 4 additions & 14 deletions Makefile-docker
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,6 @@ export PYTHON_COMMAND=python3
export PIP_COMMAND=$(PYTHON_COMMAND) -m pip
APP=src/olympia/

NODE_MODULES := $(NPM_CONFIG_PREFIX)node_modules/

REQUIRED_FILES := \
Makefile \
Makefile-os \
Makefile-docker \
/deps/package.json \
/deps/package-lock.json \
/addons-server-docker-container \

# Build list of dependencies to install
DEPS = pip prod
# If we're running a development image, then we should install the development dependencies
Expand Down Expand Up @@ -88,7 +78,7 @@ setup-ui-tests:
lint: ## lint the code
ruff check .
ruff format --check .
NODE_PATH=$(NODE_MODULES) npm exec $(NPM_ARGS) -- prettier --check '**'
npm exec $(NPM_ARGS) -- prettier --check '**'
curlylint src/

lint-codestyle: lint
Expand Down Expand Up @@ -193,15 +183,15 @@ test_failed: ## rerun the failed tests from the previous run

.PHONY: run_js_tests
run_js_tests: ## Run the JavaScript test suite (requires compiled/compressed assets).
NODE_PATH=$(NODE_MODULES) npm exec $(NPM_ARGS) -- jest tests/js
npm exec $(NPM_ARGS) -- jest tests/js

.PHONY: watch_js_tests
watch_js_tests: ## Run+watch the JavaScript test suite (requires compiled/compressed assets).
NODE_PATH=$(NODE_MODULES) npm exec $(NPM_ARGS) -- jest --watch
npm exec $(NPM_ARGS) -- jest --watch

.PHONY: format
format: ## Autoformat our codebase.
NODE_PATH=$(NODE_MODULES) npm exec $(NPM_ARGS) -- prettier --write '**'
npm exec $(NPM_ARGS) -- prettier --write '**'
ruff check --fix-only .
ruff format .

Expand Down
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ services:
volumes:
# used by: web, worker, nginx
- ${HOST_MOUNT_SOURCE:?}:/data/olympia
- ${HOST_MOUNT_SOURCE:?}deps:/deps
- ${HOST_MOUNT_SOURCE:?}deps:/data/olympia/deps
- data_site_static:/data/olympia/site-static
- ${HOST_MOUNT_SOURCE:?}storage:/data/olympia/storage
worker:
Expand All @@ -64,7 +64,7 @@ services:
]
volumes:
- ${HOST_MOUNT_SOURCE:?}:/data/olympia
- ${HOST_MOUNT_SOURCE:?}deps:/deps
- ${HOST_MOUNT_SOURCE:?}deps:/data/olympia/deps
- ${HOST_MOUNT_SOURCE:?}storage:/data/olympia/storage
extra_hosts:
- "olympia.test:127.0.0.1"
Expand Down
6 changes: 3 additions & 3 deletions docker/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ fi
NEW_HOST_UID=$(get_olympia_uid)
OLYMPIA_ID_STRING="${NEW_HOST_UID}:$(get_olympia_gid)"

# If we are on production mode, update the ownership of /data/olympia and /deps to match the new id
# If we are on production mode, update the ownership of /data/olympia to match the new id
if [[ "${HOST_MOUNT}" == "production" ]]; then
echo "Updating ownership of /data/olympia and /deps to ${OLYMPIA_ID_STRING}"
chown -R ${OLYMPIA_ID_STRING} /data/olympia /deps
echo "Updating ownership of /data/olympia to ${OLYMPIA_ID_STRING}"
chown -R ${OLYMPIA_ID_STRING} /data/olympia
fi

cat <<EOF | su -s /bin/bash $OLYMPIA_USER
Expand Down
4 changes: 2 additions & 2 deletions docs/topics/development/building_and_running_services.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ The Dockerfile for the **addons-server** project uses a multi-stage build to opt

3. **Mounts in Docker Compose**:
- **Mounting Local Repository**: The volume `.:/data/olympia` mounts the local Git repository into the container, allowing real-time changes to files within the container.
- **Mounting Dependencies**: The volume `./deps:/deps` mounts the dependencies directory, enabling better caching across builds and providing visibility for debugging directly on the host.
- **Mounting Dependencies**: The volume `./deps:/data/olympia/deps` mounts the dependencies directory, enabling better caching across builds and providing visibility for debugging directly on the host.

4. **Environment Variables for OLYMPIA_USER**:
- **Development Setup**: The `OLYMPIA_UID` .env variable is set to the host user ID, ensuring that the container runs with the correct permissions.
Expand Down Expand Up @@ -178,4 +178,4 @@ Additionally this volume is "external" to allow the volume to persist across con
We additionally mount serval local directories to the web/worker containers.

- **.:/data/olympia**: Mounts the local repository into the container to allow real-time changes to files within the container.
- **./deps:/deps**: Mounts the dependencies directory to enable better caching across builds and provide visibility for debugging directly on the host.
- **./deps:/data/olympia/deps**: Mounts the dependencies directory to enable better caching across builds and provide visibility for debugging directly on the host.
16 changes: 7 additions & 9 deletions docs/topics/development/dependency_management.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ Managing dependencies effectively is crucial for maintaining a stable and consis

## Python Dependencies

Python dependencies are managed using the Makefile and requirements files. All dependencies are installed into the `/deps` directory, which centralizes dependency management and simplifies data mounts.
Python dependencies are managed using the Makefile and requirements files. All dependencies are installed into the `/data/olympia/deps` directory, which centralizes dependency management and simplifies data mounts.

- **Environment Variables**: The project sets environment variables for Python CLIs to install dependencies in specific locations. This includes setting paths for `PIP_CACHE_DIR`, `PIP_SRC`, and others to use the `/deps` directory.
- **Environment Variables**: The project sets environment variables for Python CLIs to install dependencies in specific locations. This includes setting paths for `PIP_CACHE_DIR`, `PIP_SRC`, and others to use the `/data/olympia/deps` directory.

- **Caching Mechanism**: By using Docker build stages, the project isolates the stages responsible for installing dependencies. This prevents these stages from re-running unless the actual dependency files are changed. Additionally, internal Python cache folders are cached, avoiding unnecessary re-downloads of packages and saving time and bandwidth.

Expand Down Expand Up @@ -66,9 +66,7 @@ Ensure to comment in the requirements file above transitive dependencies which d

## Node.js Dependencies

Node.js dependencies are managed using npm. Similar to Python dependencies, Node.js dependencies are installed into the `/deps` directory.

- **Environment Variables**: Environment variables are set for Node.js CLIs to ensure that dependencies are installed in the `/deps` directory. This includes setting paths for `NPM_CONFIG_PREFIX` and `NPM_CACHE_DIR`.
Node.js dependencies are managed using npm.

- **Caching Mechanism**: Node.js dependencies are also cached using Docker build stages. Internal npm cache folders are cached to avoid re-downloading packages unnecessarily.

Expand All @@ -86,19 +84,19 @@ NPM is a fully-featured package manager, so you can use the standard CLI.

The Dockerfile uses build stages to isolate the dependency installation process. This ensures that stages do not re-run unless the dependency files themselves change. The caching mechanism includes:

- **Dependency Cache**: Both Python and Node.js dependencies are cached in the `/deps` directory.
- **Dependency Cache**: Both Python and Node.js dependencies are cached in the `/data/olympia/deps` directory.
- **Cache Folders**: Internal cache folders for pip and npm are themselves cached to speed up the build process.

## GitHub Actions Cache

The project uses a custom GitHub Actions action (`./.github/actions/cache-deps`) to cache the `/deps` folder. This action significantly increases install times for CI runs by leveraging the GitHub Actions cache.
The project uses a custom GitHub Actions action (`./.github/actions/cache-deps`) to cache the `/data/olympia/deps` folder. This action significantly increases install times for CI runs by leveraging the GitHub Actions cache.

```yaml
- name: Cache dependencies
uses: ./.github/actions/cache-deps
```

By caching the `/deps` folder, the project ensures that dependencies are quickly restored in CI environments, reducing overall build and test times.
By caching the `/data/olympia/deps` folder, the project ensures that dependencies are quickly restored in CI environments, reducing overall build and test times.

## Updating/Installing Dependencies

Expand All @@ -109,4 +107,4 @@ make up
```

This will rebuild the Docker image with the current dependencies specified in the `requirements` and `package.json` files.
We do not support updating dependencies in a running container as the /deps folder is not writable by the olympia user.
We do not support updating dependencies in a running container as the /data/olympia/deps folder is not writable by the olympia user.
2 changes: 1 addition & 1 deletion docs/topics/development/performance_and_optimization.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Docker layer caching is a powerful feature that significantly speeds up the buil
export DOCKER_BUILDKIT=1
```

- **GitHub Actions Cache**: The custom action (`./.github/actions/cache-deps`) caches the `/deps` folder, leveraging GitHub Actions cache to improve CI run times.
- **GitHub Actions Cache**: The custom action (`./.github/actions/cache-deps`) caches the `/data/olympia/deps` folder, leveraging GitHub Actions cache to improve CI run times.

## Performance Testing

Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ classifiers = [

[tool.ruff]
exclude = [
"deps",
"node_modules",
"docs",
"static",
".git",
Expand Down
31 changes: 16 additions & 15 deletions scripts/install_deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
import sys


def copy_package_json():
"""Copy package.json files to deps directory if they exist."""
try:
shutil.copy('/data/olympia/package.json', '/deps')
shutil.copy('/data/olympia/package-lock.json', '/deps')
except (IOError, OSError):
pass # Ignore if files don't exist or can't be copied
def clean_dir(dir_path, filter):
if not os.path.exists(dir_path):
return

for item in os.listdir(dir_path):
item_path = os.path.join(dir_path, item)
if os.path.isdir(item_path) and item not in filter:
shutil.rmtree(item_path)


def main(targets):
Expand All @@ -21,6 +22,8 @@ def main(targets):
DOCKER_TAG = os.environ.get('DOCKER_TAG', 'local')
DOCKER_TARGET = os.environ.get('DOCKER_TARGET', '')
OLYMPIA_DEPS = os.environ.get('OLYMPIA_DEPS', '')
DEPS_DIR = os.environ.get('DEPS_DIR')
NPM_DEPS_DIR = os.environ.get('NPM_DEPS_DIR')

if not targets:
raise ValueError('No targets specified')
Expand All @@ -31,23 +34,21 @@ def main(targets):
f'DOCKER_TAG: {DOCKER_TAG} \n',
f'DOCKER_TARGET: {DOCKER_TARGET} \n',
f'OLYMPIA_DEPS: {OLYMPIA_DEPS} \n',
f'DEPS_DIR: {DEPS_DIR} \n',
f'NPM_DEPS_DIR: {NPM_DEPS_DIR} \n',
)

# If we are installing production dependencies or on a non local image
# we always remove existing deps as we don't know what was previously
# installed or in the host ./deps directory before running this script
# installed or in the host ./deps or ./node_modules directory
# before running this script
if 'local' not in DOCKER_TAG or OLYMPIA_DEPS == 'production':
print('Removing existing deps')
for item in os.listdir('/deps'):
item_path = os.path.join('/deps', item)
if os.path.isdir(item_path) and item != 'cache':
shutil.rmtree(item_path)
clean_dir(DEPS_DIR, ['cache'])
clean_dir(NPM_DEPS_DIR, [])
else:
print('Updating existing deps')

# Copy package.json files
copy_package_json()

# Prepare the includes lists
pip_includes = []
npm_includes = []
Expand Down
6 changes: 3 additions & 3 deletions src/olympia/amo/fixtures/sentry_event.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
"stacktrace": {
"frames": [
{
"abs_path": "/deps/lib/python3.9/site-packages/django/core/handlers/exception.py",
"abs_path": "/data/olympia/deps/lib/python3.9/site-packages/django/core/handlers/exception.py",
"context_line": " response = get_response(request)",
"filename": "django/core/handlers/exception.py",
"function": "inner",
Expand Down Expand Up @@ -142,7 +142,7 @@
}
},
{
"abs_path": "/deps/lib/python3.9/site-packages/django/core/handlers/base.py",
"abs_path": "/data/olympia/deps/lib/python3.9/site-packages/django/core/handlers/base.py",
"context_line": " response = wrapped_callback(request, *callback_args, **callback_kwargs)",
"filename": "django/core/handlers/base.py",
"function": "_get_response",
Expand Down Expand Up @@ -175,7 +175,7 @@
}
},
{
"abs_path": "/deps/lib/python3.9/site-packages/django/views/decorators/cache.py",
"abs_path": "/data/olympia/deps/lib/python3.9/site-packages/django/views/decorators/cache.py",
"context_line": " response = view_func(request, *args, **kwargs)",
"filename": "django/views/decorators/cache.py",
"function": "_wrapped_view_func",
Expand Down
Loading
Loading