diff --git a/.github/workflows/build-all-on-macos.yml b/.github/workflows/build-all-on-macos.yml index 7539dd9..9c16511 100644 --- a/.github/workflows/build-all-on-macos.yml +++ b/.github/workflows/build-all-on-macos.yml @@ -21,6 +21,17 @@ jobs: uses: actions/checkout@v4 - name: move fresh clone to OF_ROOT run: cp -r ../$(echo ${{ github.repository }} | cut -d '/' -f 2) ${{ vars.ADDONS_DIR }} + - name: download addon dependencies + working-directory: ${{ vars.ADDONS_DIR }} + run: bash ofxEmotiBit/scripts/download-dependencies.sh ${{ vars.ADDONS_DIR }} + - name: record dependency commits + working-directory: ${{ vars.ADDONS_DIR }} + run: bash ofxEmotiBit/scripts/record-dependencies.sh ${{ vars.ADDONS_DIR }} macos + - name: upload dependencies report + uses: actions/upload-artifact@v4 + with: + name: dependencies-report-macos + path: ${{ vars.OFXEMOTIBIT_DIR }}/dependencies-report-macos.txt build-oscilloscope-macos: needs: clone-macos runs-on: [self-hosted, macOS] @@ -104,3 +115,11 @@ jobs: with: name: EmotiBitSoftware_v${{ steps.get_version.outputs.version }}-macOS path: ${{ vars.OFXEMOTIBIT_DIR }}/stageRelease/EmotiBitSoftware-macos-${{ steps.get_version.outputs.version }}/ + cleanup-dependencies-macos: + needs: [build-oscilloscope-macos, build-dataparser-macos, build-firmwareinstaller-macos, build-slideplayer-macos] + runs-on: [self-hosted, macOS] + environment: RUNNER-MACOS + steps: + - name: remove cloned dependencies + working-directory: ${{ vars.ADDONS_DIR }} + run: bash ofxEmotiBit/scripts/download-dependencies.sh --cleanup ${{ vars.ADDONS_DIR }} diff --git a/.github/workflows/build-all-on-win.yaml b/.github/workflows/build-all-on-win.yaml index 39833fb..d74e6d9 100644 --- a/.github/workflows/build-all-on-win.yaml +++ b/.github/workflows/build-all-on-win.yaml @@ -25,6 +25,19 @@ jobs: run: | echo ${{ github.repository }} | cut -d '/' -f 2 cp -r ..\\$(echo ${{ github.repository }} | cut -d '/' -f 2) ${{ vars.ADDONS_DIR }} + - name: download addon dependencies + shell: bash + working-directory: ${{ vars.ADDONS_DIR }} + run: bash ofxEmotiBit/scripts/download-dependencies.sh "${{ vars.ADDONS_DIR }}" + - name: record dependency commits + shell: bash + working-directory: ${{ vars.ADDONS_DIR }} + run: bash ofxEmotiBit/scripts/record-dependencies.sh "${{ vars.ADDONS_DIR }}" windows + - name: upload dependencies report + uses: actions/upload-artifact@v4 + with: + name: dependencies-report-windows + path: ${{ vars.OFXEMOTIBIT_DIR }}/dependencies-report-windows.txt build-oscilloscope-windows: needs: clone-windows runs-on: [self-hosted, Windows] @@ -159,4 +172,13 @@ jobs: uses: actions/upload-artifact@v4 with: name: EmotiBitSoftware_v${{ steps.get_version.outputs.version }}-Windows - path: ${{ vars.OFXEMOTIBIT_DIR }}\\stageRelease\\EmotiBitSoftware-Windows-${{ steps.get_version.outputs.version }} \ No newline at end of file + path: ${{ vars.OFXEMOTIBIT_DIR }}\\stageRelease\\EmotiBitSoftware-Windows-${{ steps.get_version.outputs.version }} + cleanup-dependencies-windows: + needs: [build-oscilloscope-windows, build-dataparser-windows, build-firmwareinstaller-windows, build-slideplayer-windows] + runs-on: [self-hosted, Windows] + environment: RUNNER-WINDOWS + steps: + - name: remove cloned dependencies + shell: bash + working-directory: ${{ vars.ADDONS_DIR }} + run: bash ofxEmotiBit/scripts/download-dependencies.sh --cleanup "${{ vars.ADDONS_DIR }}" \ No newline at end of file diff --git a/.github/workflows/create-draft-release.yml b/.github/workflows/create-draft-release.yml index 9c6aebd..97f7bf8 100644 --- a/.github/workflows/create-draft-release.yml +++ b/.github/workflows/create-draft-release.yml @@ -43,6 +43,50 @@ jobs: skip_unpack: true continue-on-error: true + - name: Download macOS dependencies report + uses: dawidd6/action-download-artifact@v6 + with: + workflow: build-all-on-macos.yml + branch: dev + name: dependencies-report-macos + path: ./ + continue-on-error: true + + - name: Download Windows dependencies report + uses: dawidd6/action-download-artifact@v6 + with: + workflow: build-all-on-win.yaml + branch: dev + name: dependencies-report-windows + path: ./ + continue-on-error: true + + - name: Download Linux dependencies report + uses: dawidd6/action-download-artifact@v6 + with: + workflow: linux-workflows.yaml + branch: dev + name: dependencies-report-linux + path: ./ + continue-on-error: true + + - name: Read dependency reports + id: read_deps + run: | + combine() { + local file=$1 label=$2 + if [ -f "$file" ]; then cat "$file"; else echo "*(${label} dependencies report not available)*"; fi + } + { + echo "deps_report<> $GITHUB_OUTPUT + - name: Generate release notes id: generate-release-notes run: | @@ -78,6 +122,9 @@ jobs: ) echo "release_notes<> $GITHUB_OUTPUT echo "$RELEASE_NOTES" >> $GITHUB_OUTPUT + echo "" >> $GITHUB_OUTPUT + echo "# Dependencies" >> $GITHUB_OUTPUT + echo "${{ steps.read_deps.outputs.deps_report }}" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT - name: Create config.txt @@ -109,5 +156,8 @@ jobs: EmotiBitSoftware_v${{ steps.get_version.outputs.version }}-macOS.zip EmotiBitSoftware_v${{ steps.get_version.outputs.version }}-Windows.zip config.txt + dependencies-report-macos.txt + dependencies-report-windows.txt + dependencies-report-linux.txt env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/linux-workflows.yaml b/.github/workflows/linux-workflows.yaml index 3325726..6eeb8ed 100644 --- a/.github/workflows/linux-workflows.yaml +++ b/.github/workflows/linux-workflows.yaml @@ -21,6 +21,17 @@ jobs: uses: actions/checkout@v4 - name: move fresh clone to OF_ROOT run: cp -r ../$(echo ${{ github.repository }} | cut -d '/' -f 2) ${{ vars.ADDONS_DIR }} + - name: download addon dependencies + working-directory: ${{ vars.ADDONS_DIR }} + run: bash ofxEmotiBit/scripts/download-dependencies.sh ${{ vars.ADDONS_DIR }} + - name: record dependency commits + working-directory: ${{ vars.ADDONS_DIR }} + run: bash ofxEmotiBit/scripts/record-dependencies.sh ${{ vars.ADDONS_DIR }} linux + - name: upload dependencies report + uses: actions/upload-artifact@v4 + with: + name: dependencies-report-linux + path: ${{ vars.OFXEMOTIBIT_DIR }}/dependencies-report-linux.txt build-oscilloscope-linux: needs: clone-linux uses: ./.github/workflows/reusable-workflow-build-oscilloscope-linux.yml @@ -36,3 +47,12 @@ jobs: test-dataparser-linux: needs: build-dataparser-linux uses: ./.github/workflows/reusable-workflow-test-dataParser-linux.yml + + cleanup-dependencies-linux: + needs: [test-oscilloscope-linux, test-dataparser-linux] + runs-on: [self-hosted, Linux] + environment: RUNNER-LINUX + steps: + - name: remove cloned dependencies + working-directory: ${{ vars.ADDONS_DIR }} + run: bash ofxEmotiBit/scripts/download-dependencies.sh --cleanup ${{ vars.ADDONS_DIR }} diff --git a/dependencies.json b/dependencies.json new file mode 100644 index 0000000..7c5e447 --- /dev/null +++ b/dependencies.json @@ -0,0 +1,13 @@ +{ + "dependencies": [ + { "name": "ofxNetworkUtils", "repo": "https://github.com/bakercp/ofxNetworkUtils.git", "ref": "stable" }, + { "name": "ofxOscilloscope", "repo": "https://github.com/produceconsumerobot/ofxOscilloscope.git", "ref": "master" }, + { "name": "ofxThreadedLogger", "repo": "https://github.com/produceconsumerobot/ofxThreadedLogger.git", "ref": "master" }, + { "name": "ofxBiquadFilter", "repo": "https://github.com/smukkejohan/ofxBiquadFilter.git", "ref": "master" }, + { "name": "ofxJSON", "repo": "https://github.com/jeffcrouse/ofxJSON.git", "ref": "master" }, + { "name": "EmotiBit_XPlat_Utils", "repo": "https://github.com/EmotiBit/EmotiBit_XPlat_Utils.git", "ref": "master" }, + { "name": "ofxLSL", "repo": "https://github.com/EmotiBit/ofxLSL.git", "ref": "master" }, + { "name": "ofxSerial", "repo": "https://github.com/EmotiBit/ofxSerial.git", "ref": "stable" }, + { "name": "ofxIO", "repo": "https://github.com/bakercp/ofxIO.git", "ref": "stable" } + ] +} diff --git a/scripts/download-dependencies.sh b/scripts/download-dependencies.sh new file mode 100755 index 0000000..d584c48 --- /dev/null +++ b/scripts/download-dependencies.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash +# download-dependencies.sh +# +# Usage: +# bash scripts/download-dependencies.sh # clone all deps +# bash scripts/download-dependencies.sh --cleanup # remove all dep clones +# +# Reads dependencies.json from the repo root. Each dependency is cloned into +# ADDONS_DIR at the specified ref (branch, tag, or commit SHA), mirroring how +# ofxEmotiBit itself is checked out and placed in ADDONS_DIR by the CI workflow. +# +# Phase 2: enforces the manifest. Run before record-dependencies.sh so the +# report reflects exactly what was downloaded. + +set -euo pipefail + +# --- argument parsing --- +CLEANUP=false +if [ "$1" = "--cleanup" ]; then + CLEANUP=true + ADDONS_DIR="$2" +else + ADDONS_DIR="$1" +fi + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(dirname "$SCRIPT_DIR")" +# On Windows, Git Bash uses MSYS2 paths (/c/...) but native Windows Python +# requires Windows-style paths (C:/...). pwd -W returns the Windows-style +# path in Git Bash; on macOS/Linux it is unrecognized and we fall back to pwd. +REPO_ROOT_PY="$(cd "$REPO_ROOT" && pwd -W 2>/dev/null || pwd)" +DEPS_JSON="$REPO_ROOT/dependencies.json" +DEPS_JSON_PY="$REPO_ROOT_PY/dependencies.json" + +if [ ! -f "$DEPS_JSON" ]; then + echo "ERROR: dependencies.json not found at $DEPS_JSON" + exit 1 +fi + +# --- cleanup mode: remove all dep directories --- +if [ "$CLEANUP" = true ]; then + echo "Cleaning up cloned dependencies from $ADDONS_DIR" + python3 -c " +import json +with open('$DEPS_JSON_PY') as f: + for d in json.load(f)['dependencies']: + print(d['name']) +" | tr -d '\r' | while read -r name; do + target="$ADDONS_DIR/$name" + if [ -d "$target" ]; then + echo " removing $name" + rm -rf "$target" + fi + done + echo "Cleanup complete." + exit 0 +fi + +# --- download mode: clone each dep at specified ref --- +echo "Downloading dependencies into $ADDONS_DIR" + +python3 -c " +import json +with open('$DEPS_JSON_PY') as f: + for d in json.load(f)['dependencies']: + print(d['name'] + ' ' + d['repo'] + ' ' + d['ref']) +" | tr -d '\r' | while IFS=' ' read -r name repo ref; do + target="$ADDONS_DIR/$name" + + if [ -d "$target" ]; then + echo "==> $name: removing existing clone" + rm -rf "$target" + fi + + echo "==> $name: cloning $repo at ref '$ref'" + git clone "$repo" "$target" + git -C "$target" checkout "$ref" + echo " resolved: $(git -C "$target" rev-parse HEAD)" +done + +echo "" +echo "All dependencies downloaded." diff --git a/scripts/record-dependencies.sh b/scripts/record-dependencies.sh new file mode 100755 index 0000000..88e5c88 --- /dev/null +++ b/scripts/record-dependencies.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +# record-dependencies.sh +# +# Usage: bash scripts/record-dependencies.sh +# +# Reads dependencies.json from the repo root, inspects each listed addon +# directory that is already present on the runner, and records its actual +# HEAD commit SHA and ref into a Markdown report file: +# dependencies-report-.txt +# +# Does NOT clone or modify any addon directory (Phase 1 — logging only). +# Run this immediately after checking out ofxEmotiBit in CI so the record +# is written before any build starts. + +set -euo pipefail + +if [ $# -lt 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +ADDONS_DIR="$1" +PLATFORM="$2" + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(dirname "$SCRIPT_DIR")" +# On Windows, Git Bash uses MSYS2 paths (/c/...) but native Windows Python +# requires Windows-style paths (C:/...). pwd -W returns the Windows-style +# path in Git Bash; on macOS/Linux it is unrecognized and we fall back to pwd. +REPO_ROOT_PY="$(cd "$REPO_ROOT" && pwd -W 2>/dev/null || pwd)" +DEPS_JSON="$REPO_ROOT/dependencies.json" +DEPS_JSON_PY="$REPO_ROOT_PY/dependencies.json" +REPORT="$REPO_ROOT/dependencies-report-${PLATFORM}.txt" + +if [ ! -f "$DEPS_JSON" ]; then + echo "ERROR: dependencies.json not found at $DEPS_JSON" + exit 1 +fi + +OFXEMOTIBIT_COMMIT=$(git -C "$REPO_ROOT" rev-parse HEAD) +OFXEMOTIBIT_REF=$(git -C "$REPO_ROOT" symbolic-ref --short HEAD 2>/dev/null || echo "(detached)") + +cat > "$REPORT" </dev/null \ + || git -C "$target" describe --tags --exact-match HEAD 2>/dev/null \ + || echo "(detached)") + else + resolved_commit="NOT FOUND" + resolved_ref="NOT FOUND" + fi + echo "| $name | \`$ref\` | \`$resolved_commit\` | \`$resolved_ref\` |" >> "$REPORT" +done + +echo "" +echo "Dependency report written to: $REPORT" +echo "" +cat "$REPORT"