-
Notifications
You must be signed in to change notification settings - Fork 14
Add a github workflow to build and test the container #81
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
base: main
Are you sure you want to change the base?
Changes from 1 commit
3f1519f
0b5eb2b
dffcbe2
9e54472
95a646e
77fd62c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| name: Build and Test Orcanode Container | ||
|
|
||
| on: | ||
| push: | ||
| branches: [main] | ||
| paths: | ||
| - 'node/**' | ||
| - 'base/**' | ||
| - '.github/workflows/build-container.yml' | ||
| tags: | ||
| - 'v*.*.*' # Trigger on version tags. | ||
| pull_request: | ||
| paths: | ||
| - 'node/**' | ||
| - 'base/**' | ||
| - '.github/workflows/build-container.yml' | ||
| workflow_dispatch: | ||
|
|
||
| jobs: | ||
| test: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
|
|
||
| - name: Build container image | ||
| run: docker build -t orcanode:test -f node/Dockerfile . | ||
|
|
||
| - name: Verify Python is available | ||
| run: docker run --rm orcanode:test python3 --version | ||
|
|
||
| - name: Verify FFmpeg is installed | ||
| run: docker run --rm orcanode:test ffmpeg -version | ||
|
|
||
| - name: Verify Jack audio is installed | ||
| run: docker run --rm orcanode:test which jackd | ||
|
|
||
| - name: Verify Python dependencies | ||
| run: docker run --rm orcanode:test python3 -c "import boto3; import inotify; print('Python deps OK')" | ||
|
|
||
| - name: Verify application scripts are present | ||
| run: docker run --rm orcanode:test ls -la /app/stream.sh | ||
|
|
||
| - name: Test container startup | ||
| run: | | ||
| # Copy .env.example to test.env and customize for CI. | ||
| cp node/.env.example test.env | ||
|
|
||
| # Replace FILLTHISIN placeholders with test values. | ||
| sed -i 's/AWS_ACCESS_KEY_ID=FILLTHISIN/AWS_ACCESS_KEY_ID=test-key-id/g' test.env | ||
| sed -i 's/AWS_SECRET_ACCESS_KEY=FILLTHISIN/AWS_SECRET_ACCESS_KEY=test-secret/g' test.env | ||
| sed -i 's/key="FILLTHISIN"/key="test-logdna-key"/g' test.env | ||
| sed -i 's/NODE_NAME=rpi_location/NODE_NAME=rpi_github_ci/g' test.env | ||
|
|
||
| # Disable loopback testing since CI environments won't have audio hardware. | ||
| sed -i 's/NODE_LOOPBACK=true/NODE_LOOPBACK=false/g' test.env | ||
|
|
||
| # Start container with env file. | ||
| docker run -d --name orcanode-test \ | ||
| --env-file test.env \ | ||
| orcanode:test || true | ||
|
|
||
| sleep 5 | ||
| echo "=== Container logs ===" | ||
| docker logs orcanode-test | ||
|
|
||
| # Check container health: accept running or cleanly exited (exit code 0) | ||
| STATUS=$(docker inspect --format='{{.State.Status}}' orcanode-test) | ||
| EXIT_CODE=$(docker inspect --format='{{.State.ExitCode}}' orcanode-test) | ||
|
|
||
| echo "Container status: $STATUS, exit code: $EXIT_CODE" | ||
|
|
||
| if [ "$STATUS" = "running" ]; then | ||
| echo "Container is running (audio hardware errors expected in CI)" | ||
| elif [ "$STATUS" = "exited" ] && [ "$EXIT_CODE" = "0" ]; then | ||
| echo "Container exited cleanly (exit code 0)" | ||
| else | ||
| echo "Container failed with status: $STATUS, exit code: $EXIT_CODE" | ||
| exit 1 | ||
| fi | ||
|
|
||
| docker stop orcanode-test || true | ||
| docker rm orcanode-test | ||
| rm test.env | ||
|
|
||
| build-and-push: | ||
| needs: test | ||
| if: github.ref == 'refs/heads/main' || github.ref_type == 'tag' || github.event_name == 'workflow_dispatch' | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| packages: write | ||
| actions: write # Required for cache-to: type=gha | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
|
|
||
| - name: Set up QEMU | ||
| uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 | ||
|
|
||
| - name: Set up Docker Buildx | ||
| uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3.6.1 | ||
|
|
||
| - name: Login to GitHub Container Registry | ||
| uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 | ||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Extract metadata | ||
| id: meta | ||
| uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 | ||
| with: | ||
| images: ghcr.io/${{ github.repository }}/orcanode | ||
| tags: | | ||
| # Semver tags on release | ||
| type=semver,pattern={{version}} | ||
| type=semver,pattern={{major}}.{{minor}} | ||
| type=semver,pattern={{major}} | ||
| # Branch-based tags | ||
| type=ref,event=branch | ||
| type=sha,prefix={{branch}}- | ||
| # Latest tag for main branch | ||
| type=raw,value=latest,enable={{is_default_branch}} | ||
|
Comment on lines
+155
to
+170
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Check the repository name to confirm the resulting image path
echo "Repository: orcasound/orcanode"
echo "Resulting image path: ghcr.io/orcasound/orcanode/orcanode"
echo ""
echo "If this is unintended, the image path should be: ghcr.io/orcasound/orcanode"Repository: orcasound/orcanode Length of output: 227 🏁 Script executed: # Check if there are other container images or references in the workflow
rg "images:" .github/workflows/ -A 2Repository: orcasound/orcanode Length of output: 290 🏁 Script executed: # Look for any documentation about container image naming in the repo
fd -e md -e txt | xargs rg -l "container|image|ghcr" 2>/dev/null | head -20Repository: orcasound/orcanode Length of output: 87 🏁 Script executed: # Check for other docker/metadata-action uses in the repository
rg "docker/metadata-action" .github/workflows/Repository: orcasound/orcanode Length of output: 186 🏁 Script executed: # Look at the broader workflow context to see if there are multiple services/images
cat -n .github/workflows/build-container.yml | head -50Repository: orcasound/orcanode Length of output: 2092 🏁 Script executed: # Check the README files for any documentation about container image naming
cat README.md | grep -i "container\|image\|ghcr" -A 2 -B 2Repository: orcasound/orcanode Length of output: 1719 🏁 Script executed: # Also check the full build-container.yml workflow to understand if there's any reason for the /orcanode suffix
cat -n .github/workflows/build-container.yml | sed -n '130,182p'Repository: orcasound/orcanode Length of output: 2446 Simplify the image path by removing the redundant The image path images: ghcr.io/${{ github.repository }}This produces the simpler and more conventional image path 🤖 Prompt for AI Agents |
||
|
|
||
| - name: Build and push multi-arch images | ||
| uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 # v6.7.0 | ||
| with: | ||
| context: . | ||
| file: ./node/Dockerfile | ||
| platforms: linux/amd64,linux/arm/v7,linux/arm64 | ||
| push: true | ||
| tags: ${{ steps.meta.outputs.tags }} | ||
| labels: ${{ steps.meta.outputs.labels }} | ||
| cache-from: type=gha | ||
| cache-to: type=gha,mode=max | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| .env | ||
| .env | ||
| .vs |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| # Orcanode Configuration Template | ||
| # Copy this file to .env and customize for your deployment | ||
| # See README.md for detailed field descriptions | ||
|
|
||
| # === AWS Credentials === | ||
| # Get these from AWS IAM Console or contact Orcasound admin | ||
| AWS_ACCESS_KEY_ID=FILLTHISIN | ||
| AWS_SECRET_ACCESS_KEY=FILLTHISIN | ||
|
|
||
| # === AWS Configuration === | ||
| AWS_METADATA_SERVICE_TIMEOUT=5 | ||
| AWS_METADATA_SERVICE_NUM_ATTEMPTS=0 | ||
| REGION=us-west-2 | ||
|
|
||
| # === S3 Bucket Selection === | ||
| BUCKET_TYPE=dev | ||
| #BUCKET_TYPE=prod | ||
|
|
||
|
dthaler marked this conversation as resolved.
|
||
| # === Node Configuration === | ||
| # Uncomment the NODE_TYPE you need: | ||
| NODE_TYPE=hls-only | ||
| #NODE_TYPE=research | ||
| #NODE_TYPE=offline | ||
|
dthaler marked this conversation as resolved.
Outdated
|
||
|
|
||
| # Unique identifier for this node (format: rpi_location) | ||
| NODE_NAME=rpi_location | ||
|
|
||
| # Audio loopback for testing (true/false/hls) | ||
| # - true: Route audio input directly to output via Jack | ||
| # - false: No loopback | ||
| # - hls: Play back the generated HLS stream with ffplay (for testing) | ||
| NODE_LOOPBACK=true | ||
| #NODE_LOOPBACK=false | ||
| #NODE_LOOPBACK=hls | ||
|
|
||
| # Audio Settings | ||
| SAMPLE_RATE=48000 | ||
| AUDIO_HW_ID=pisound | ||
| CHANNELS=1 | ||
|
|
||
| # === Logging Configuration === | ||
| # Used by logspout sidecar - get credentials from Orcasound admin | ||
| SYSLOG_URL=syslog://syslog-a.logdna.com:37043 | ||
| SYSLOG_STRUCTURED_DATA='logdna@48950 key="FILLTHISIN" tag="docker"' | ||
|
|
||
| # === Stream Configuration === | ||
| FLAC_DURATION=30 | ||
| SEGMENT_DURATION=10 | ||
|
|
||
| # === System Configuration === | ||
| LC_ALL=C.UTF-8 | ||
|
|
||
| # === Field Descriptions === | ||
| # | ||
| # AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY: | ||
| # AWS credentials for S3 bucket access | ||
| # | ||
| # BUCKET_TYPE: | ||
| # - dev: Development bucket (dev-streaming-orcasound-net) | ||
| # - prod: Production bucket (audio-orcasound-net) | ||
| # - custom: Use custom buckets (requires BUCKET_STREAMING and BUCKET_ARCHIVE) | ||
| # | ||
| # NODE_TYPE: | ||
| # - hls-only: Stream HLS segments only (most common) | ||
| # - research: Stream HLS + archive FLAC files | ||
| # - offline: Local testing mode | ||
| # | ||
| # NODE_NAME: | ||
| # Unique identifier in format: rpi_location (e.g., rpi_bush_point, rpi_port_townsend) | ||
| # | ||
| # AUDIO_HW_ID: | ||
| # Sound card identifier. Find with: arecord -l | ||
| # Use logical name (pisound, USB) not device numbers (0,0) | ||
| # | ||
| # SAMPLE_RATE: | ||
| # Audio sampling rate in Hz (48000 for standard, 192000 for research) | ||
| # | ||
| # CHANNELS: | ||
| # Number of audio channels (1=mono, 2=stereo) | ||
| # | ||
| # SEGMENT_DURATION: | ||
| # Seconds per HLS segment (typically 10) | ||
| # | ||
| # FLAC_DURATION: | ||
| # Seconds per archived FLAC file (research mode only, typically 30) | ||
| # | ||
| # SYSLOG_URL / SYSLOG_STRUCTURED_DATA: | ||
| # LogDNA/Mezmo credentials for centralized logging via logspout | ||
| # Request credentials in #hydrophone-nodes on Orcasound Slack | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # Environment variables with secrets | ||
| .env | ||
|
|
||
| # But keep the example | ||
| !.env.example |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,37 +1,54 @@ | ||
| # Node Dockerfile for hydrophone streaming | ||
| # use base image for project | ||
|
|
||
| FROM orcastream/orcabase:latest | ||
| MAINTAINER Orcasound <orcanode-devs@orcasound.net> | ||
|
|
||
| ###### hack to get ffmpeg to build | ||
| # RUN apt-get update && apt-get install -y --no-install-recommends libraspberrypi-dev raspberrypi-kernel-headers | ||
| # RUN git clone https://github.com/raspberrypi/userland.git | ||
| # RUN cd userland/host_applications/linux/apps/hello_pi && ./rebuild.sh | ||
|
|
||
|
|
||
| ###### Install Jack ################################# | ||
|
|
||
| ENV DEBIAN_FRONTEND noninteractive | ||
| RUN apt-get update && apt-get install -y --no-install-recommends jack-capture | ||
| RUN apt-get update && apt-get install -y --no-install-recommends jackd1 | ||
|
|
||
| # Install ALSA and GPAC | ||
| #RUN apt-get update && apt-get install -y --no-install-recommends \ | ||
| # alsa-utils \ | ||
| # gpac | ||
|
|
||
| ############################### Copy files ##################################### | ||
|
|
||
| COPY . . | ||
|
|
||
| ################################## TODO ######################################## | ||
| # Do the following: | ||
| # - Add pisound driver curl command | ||
| # - Add other audio drivers and configure via CLI if possible? | ||
| # - Remove "misc tools" and other installs no longer needed (upon Resin.io deployment)? | ||
|
|
||
| ################################# Miscellaneous ################################ | ||
|
|
||
| # Clean up APT when done. | ||
| RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* | ||
| # Multi-arch self-contained build for CI/CD deployment | ||
|
|
||
| FROM python:3.11-slim-bookworm | ||
|
|
||
| LABEL org.opencontainers.image.source="https://github.com/orcasound/orcanode" | ||
| LABEL org.opencontainers.image.description="Orcasound hydrophone streaming node" | ||
| LABEL org.opencontainers.image.authors="Orcasound <orcanode-devs@orcasound.net>" | ||
|
|
||
| # Install system dependencies | ||
| RUN export DEBIAN_FRONTEND=noninteractive \ | ||
| && apt-get update && apt-get install -y --no-install-recommends \ | ||
| ffmpeg \ | ||
| jack-capture \ | ||
| jackd2 \ | ||
| alsa-utils \ | ||
| git \ | ||
| curl \ | ||
| && apt-get clean \ | ||
| && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* | ||
|
|
||
| # Install Python dependencies | ||
| RUN pip3 install --no-cache-dir \ | ||
| boto3 \ | ||
| inotify | ||
|
|
||
| # Set working directory | ||
| WORKDIR /app | ||
|
|
||
| # Copy node application files first | ||
| COPY node/ ./ | ||
|
|
||
| # Copy Python upload scripts from base directory (overwrites if they exist in node/) | ||
| COPY base/upload_s3.py ./ | ||
| COPY base/upload_flac_s3.py ./ | ||
|
dthaler marked this conversation as resolved.
|
||
|
|
||
| # Set environment defaults | ||
| ENV SAMPLE_RATE=48000 \ | ||
| STREAM_RATE=48000 \ | ||
| CHANNELS=1 \ | ||
| NODE_TYPE=hls-only | ||
|
|
||
| # Make scripts executable | ||
| RUN chmod +x *.sh | ||
|
|
||
| # Ensure .env.example is available for reference | ||
| RUN if [ -f .env.example ]; then \ | ||
| echo ".env.example is available at /app/.env.example"; \ | ||
| else \ | ||
| echo "Warning: .env.example not found"; \ | ||
| fi | ||
|
|
||
| # Run the streaming script | ||
| CMD ["./stream.sh"] | ||
Uh oh!
There was an error while loading. Please reload this page.