diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 1235831f..3786ef2a 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -8,32 +8,80 @@ name: CI Pipeline on: push: branches: [ "main" ] +####### Uncomment this to test the CI pipeline in a PR +####### You'll also need to comment the rules containing {{branch}} +####### in the `Extract Docker metadata` step +# pull_request: +# branches: [ "main" ] env: # Use docker.io for Docker Hub if empty REGISTRY: ghcr.io # github.repository as / - IMAGE_NAME: ${{ github.repository }} + REGISTRY_PATH: ${{ github.repository }} TEST_TAG: user/app:test jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # This might be unnecessary as tests are not + # multiplatform + - name: Setup Docker buildx + uses: docker/setup-buildx-action@v3.9.0 + + # Build but don't push Docker image with Buildx + # https://github.com/docker/build-push-action + - name: Build test image + id: build-test + uses: docker/build-push-action@v6.13.0 + with: + context: . + load: true + target: dev + tags: ${{ env.TEST_TAG }} + cache-from: type=gha + cache-to: type=gha,mode=max + + # This is a barrier check to make sure we push a functional + # docker image, we can avoid linting + - name: Run tests in the test image + run: | + docker run --rm ${{ env.TEST_TAG }} make ci-test + build: runs-on: ubuntu-latest + needs: test permissions: contents: read packages: write # This is used to complete the identity challenge # with sigstore/fulcio when running outside of PRs. id-token: write - + strategy: + matrix: + docker_target: + - http + - socketio + - dramatiq steps: + # GitHub gives only repository complete in / format. + # Need some manual sheanigans + # Set IMAGE_NAME so we can push to // + - name: Set ENV variables + run: | + echo "IMAGE_NAME=${GITHUB_REPOSITORY#$GITHUB_REPOSITORY_OWNER/}" >> $GITHUB_ENV + - name: Checkout repository uses: actions/checkout@v4 - name: Set up QEMU uses: docker/setup-qemu-action@v3 - # Install the cosign tool except on PR + # Install the cosign tool # https://github.com/sigstore/cosign-installer - name: Install cosign uses: sigstore/cosign-installer@v3.8.0 @@ -41,7 +89,7 @@ jobs: - name: Setup Docker buildx uses: docker/setup-buildx-action@v3.9.0 - # Login against a Docker registry except on PR + # Login against a Docker registry # https://github.com/docker/login-action - name: Log into registry ${{ env.REGISTRY }} uses: docker/login-action@v3.3.0 @@ -50,23 +98,6 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - # Build and push Docker image with Buildx - # https://github.com/docker/build-push-action - - name: Build test image - id: build-test - uses: docker/build-push-action@v6.13.0 - with: - context: . - load: true - target: dev - tags: ${{ env.TEST_TAG }} - cache-from: type=gha - cache-to: type=gha,mode=max - - - name: Test - run: | - docker run --rm ${{ env.TEST_TAG }} make ci-test - # Extract metadata (tags, labels) for Docker # https://github.com/docker/metadata-action - name: Extract Docker metadata @@ -74,8 +105,9 @@ jobs: uses: docker/metadata-action@v5.6.1 with: # list of Docker images to use as base name for tags + # //- images: | - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }} # generate Docker tags based on the following events/attributes tags: | type=sha @@ -89,7 +121,7 @@ jobs: uses: docker/build-push-action@v6.13.0 with: context: . - target: http_app + target: ${{ matrix.docker_target }} platforms: linux/amd64,linux/arm64 push: true tags: ${{ steps.meta.outputs.tags }} diff --git a/.gitlab_ci/build.yml b/.gitlab_ci/build.yml index 600fcb14..74b3c2d6 100644 --- a/.gitlab_ci/build.yml +++ b/.gitlab_ci/build.yml @@ -17,7 +17,7 @@ build-http-app-amd64: variables: DOCKER_IMAGE_NAME: $CI_PROJECT_NAME-http DOCKER_PLATFORM: "linux/amd64" - DOCKER_TARGET: http_app + DOCKER_TARGET: http tags: - saas-linux-small-amd64 rules: @@ -32,7 +32,7 @@ build-http-app-arm64: variables: DOCKER_IMAGE_NAME: $CI_PROJECT_NAME-http DOCKER_PLATFORM: "linux/arm64" - DOCKER_TARGET: http_app + DOCKER_TARGET: http tags: - saas-linux-small-arm64 rules: diff --git a/Dockerfile b/Dockerfile index 162cd292..5785aa0e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -69,30 +69,30 @@ RUN --mount=type=cache,target=~/.cache/uv \ # Create the base app with the common python packages FROM base AS base_app USER nonroot -COPY --chown=nonroot:nonroot src/migrations ./migrations +COPY --chown=nonroot:nonroot src/common ./common COPY --chown=nonroot:nonroot src/domains ./domains COPY --chown=nonroot:nonroot src/gateways ./gateways -COPY --chown=nonroot:nonroot src/common ./common +COPY --chown=nonroot:nonroot src/migrations ./migrations COPY --chown=nonroot:nonroot src/alembic.ini . # Copy the http python package and requirements from relevant builder -FROM base_app AS http_app +FROM base_app AS http COPY --from=http_builder /venv /venv COPY --chown=nonroot:nonroot src/http_app ./http_app -# Run CMD using array syntax, so it's uses `exec` and runs as PID1 +# Run CMD using array syntax, so it uses `exec` and runs as PID1 CMD ["opentelemetry-instrument", "python", "-m", "http_app"] # Copy the socketio python package and requirements from relevant builder -FROM base_app AS socketio_app -COPY --from=socketio_builder_builder /venv /venv +FROM base_app AS socketio +COPY --from=socketio_builder /venv /venv COPY --chown=nonroot:nonroot src/socketio_app ./socketio_app -# Run CMD using array syntax, so it's uses `exec` and runs as PID1 +# Run CMD using array syntax, so it uses `exec` and runs as PID1 CMD ["opentelemetry-instrument", "python", "-m", "socketio_app"] # Copy the dramatiq python package and requirements from relevant builder -FROM base_app AS dramatiq_app +FROM base_app AS dramatiq COPY --from=dramatiq_builder /venv /venv COPY --chown=nonroot:nonroot src/dramatiq_worker ./dramatiq_worker -# Run CMD using array syntax, so it's uses `exec` and runs as PID1 +# Run CMD using array syntax, so it uses `exec` and runs as PID1 # TODO: Review processes/threads CMD ["opentelemetry-instrument", "dramatiq", "-p", "1", "-t", "1", "dramatiq_worker"] diff --git a/tests/socketio_app/namespaces/test_chat.py b/tests/socketio_app/namespaces/test_chat.py index b50c0c40..cd327b4f 100644 --- a/tests/socketio_app/namespaces/test_chat.py +++ b/tests/socketio_app/namespaces/test_chat.py @@ -10,7 +10,6 @@ def chat_namespace(): return ChatNamespace("/chat") -@pytest.mark.asyncio async def test_on_connect(chat_namespace): sid = "test_session_id" environ = {} @@ -19,7 +18,6 @@ async def test_on_connect(chat_namespace): chat_namespace.on_connect(sid, environ) -@pytest.mark.asyncio async def test_on_disconnect(chat_namespace): sid = "test_session_id" reason = "test_reason" @@ -28,7 +26,6 @@ async def test_on_disconnect(chat_namespace): chat_namespace.on_disconnect(sid, reason) -@pytest.mark.asyncio async def test_on_echo_message(chat_namespace): sid = "test_session_id" test_data = {"message": "Hello, World!"}