diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4ff90a7..bed48a5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,39 +1,12 @@ name: Create release on: workflow_dispatch: - pull_request: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true jobs: - lint-format: - name: Lint and format check - runs-on: ubuntu-latest - if: github.event_name == 'pull_request' - steps: - - uses: actions/checkout@v4 - if: always() - - name: Install Ruff and autopep8 - if: always() - run: pip install ruff autopep8 - - name: Python lint check (Ruff) - if: always() - run: ruff check --output-format=github -v plugin/ - - name: Python lint check (autopep8) - if: always() - run: autopep8 --diff plugin/ - - name: Install server dependencies - if: always() - run: cd server && yarn install - - name: Server lint check (ESlint) - if: always() - run: cd server && npx eslint --max-warnings=0 src/ - - name: Server format check (Prettier) - if: always() - run: cd server && npx prettier --check 'src/**/*.{js,ts}' - release: name: Release to Github permissions: @@ -67,7 +40,7 @@ jobs: EOF echo "::endgroup::" - name: Bundle - if: github.event_name != 'pull_request' && format('refs/heads/{0}', github.event.repository.default_branch) == github.ref + if: format('refs/heads/{0}', github.event.repository.default_branch) == github.ref # only release on default branch id: bundle env: @@ -96,7 +69,7 @@ jobs: echo "RELEASE_BODY=$r" | tee -a $GITHUB_OUTPUT # <--- Set environment variable - name: Create Release on Github - if: github.event_name != 'pull_request' && format('refs/heads/{0}', github.event.repository.default_branch) == github.ref + if: format('refs/heads/{0}', github.event.repository.default_branch) == github.ref # only release on default branch uses: svenstaro/upload-release-action@v2 with: @@ -110,7 +83,7 @@ jobs: release_pypi: name: Release to PyPI - if: github.event_name != 'pull_request' && format('refs/heads/{0}', github.event.repository.default_branch) == github.ref + if: format('refs/heads/{0}', github.event.repository.default_branch) == github.ref # only release on default branch runs-on: ubuntu-latest permissions: @@ -169,8 +142,6 @@ jobs: tags: | type=raw,value=latest,enable={{is_default_branch}} # mark as latest only if built on default branch of repository - type=raw,value=ci,enable={{is_default_branch}} - # mark as ci only if built on default branch of repository type=raw,value=${{ needs.release.outputs.version }},enable={{is_default_branch}} # add the new git tag only if built on default branch of repository type=sha @@ -178,7 +149,6 @@ jobs: type=ref,event=pr - name: Login to DockerHub - if: github.event_name != 'pull_request' uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} @@ -192,21 +162,19 @@ jobs: with: context: server/ file: server/Dockerfile - platforms: ${{ github.event_name != 'pull_request' && 'linux/amd64,linux/arm64' || 'linux/amd64' }} - push: ${{ github.event_name != 'pull_request' }} + platforms: "linux/amd64,linux/arm64" + push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} annotations: ${{ steps.meta.outputs.annotations }} - name: Add official repository link to README.md - if: github.event_name != 'pull_request' run: | printf '%s\n\n' \ "Official repository: <${{ github.server_url }}/${{ github.repository }}>" > ./README.md.new cat ./README.md >> ./README.md.new && mv -f ./README.md.new ./README.md - name: Update repo description - if: github.event_name != 'pull_request' uses: peter-evans/dockerhub-description@v4 with: username: ${{ secrets.DOCKERHUB_USERNAME }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..cad80eb --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,131 @@ +name: Run tests +on: + workflow_dispatch: + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + TEST_ARGS: -vF --print-traffic --no-simulate --color always -f "b*" -S "filesize:10M" --exec "rm -f" + +jobs: + lint-format: + name: Lint and format check + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + steps: + - uses: actions/checkout@v4 + - name: Install Ruff and autopep8 + run: pip install ruff autopep8 + - name: Python lint check (Ruff) + run: ruff check --output-format=github -v plugin/ + - name: Python lint check (autopep8) + if: always() + run: autopep8 --diff plugin/ + - name: Install server dependencies + if: always() + run: cd server && yarn install + - name: Server lint check (ESlint) + if: always() + run: cd server && npx eslint --max-warnings=0 src/ + - name: Server format check (Prettier) + if: always() + run: cd server && npx prettier --check 'src/**/*.{js,ts}' + + script-method: + name: Test plugin (script method) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Download yt-dlp + run: curl -L https://github.com/yt-dlp/yt-dlp-nightly-builds/releases/latest/download/yt-dlp -o yt-dlp && chmod +x ./yt-dlp + - name: Install and build server dependencies + run: cd server/ && yarn install --frozen-lockfile && npx tsc + - name: Install plugin + run: | + mkdir -p ~/yt-dlp-plugins/bgutil-ytdlp-pot-provider/ + curl -L "https://github.com/coletdjnz/yt-dlp-get-pot/releases/download/v0.1.1/yt-dlp-get-pot.zip" -o ~/yt-dlp-plugins/yt-dlp-get-pot.zip + cp -r plugin/ ~/yt-dlp-plugins/ + - name: Test script method + shell: bash + run: | + script_response=$(./yt-dlp ${{ env.TEST_ARGS }} --extractor-args "youtube:getpot_bgutil_script=server/build/generate_once.js" dQw4w9WgXcQ 2>&1) || \ + echo "::error title=Failed to run yt-dlp when testing script::\ + yt-dlp returned $? exit status" + + echo "::group::Logs from yt-dlp" + printf "%s\n" "$script_response" + echo "::endgroup::" + if [[ "$script_response" != *"BgUtilScriptPot: Generating POT via script: "* ]]; then + echo "::error title=BgUtilScriptPot was not invoked,file=plugin/yt_dlp_plugins/extractor/getpot_bgutil_script.py::\ + BgUtilScriptPot was not invoked" + exit 1 + fi + + server-method: + name: Test plugin (server method) + runs-on: ubuntu-latest + env: + PORT: ${{ 4426 }} + # Interval/Timeout in seconds to wait for the server to be up + INTERVAL: ${{ 0.4 }} + TIMEOUT: ${{ 7.5 }} + steps: + - uses: actions/checkout@v4 + - name: Download yt-dlp + run: curl -L https://github.com/yt-dlp/yt-dlp-nightly-builds/releases/latest/download/yt-dlp -o yt-dlp && chmod +x ./yt-dlp + - name: Install plugin + run: | + mkdir -p ~/yt-dlp-plugins/bgutil-ytdlp-pot-provider/ + curl -L "https://github.com/coletdjnz/yt-dlp-get-pot/releases/download/v0.1.1/yt-dlp-get-pot.zip" -o ~/yt-dlp-plugins/yt-dlp-get-pot.zip + cp -r plugin/ ~/yt-dlp-plugins/ + - name: Build Docker image + uses: docker/build-push-action@v6 + with: + context: server/ + file: server/Dockerfile + load: true + tags: brainicism/bgutil-ytdlp-pot-provider:ci + - name: Test server method + timeout-minutes: 3 + shell: bash + run: | + ping() { + until curl -o- --silent --fail http://127.0.0.1:${{ env.PORT }}/ping 2>&1; do + sleep ${1:-0.5} + done + } + export -f ping + + docker run --name bgutil-provider -d -p ${{ env.PORT }}:4416 brainicism/bgutil-ytdlp-pot-provider:ci + + echo "Waiting for server to be up..." + PING_RESP=$(timeout ${{ env.TIMEOUT }} bash -c "ping ${{ env.INTERVAL }}") || \ + (echo "::error title=Timeout reached,file=server/src/main.ts::\ + Timeout reached before the server is up." && exit 1) + + echo "::group::Response from HTTP server" + echo "$PING_RESP" | jq -C + echo "::endgroup::" + + script_response=$(./yt-dlp ${{ env.TEST_ARGS }} --extractor-args "youtube:getpot_bgutil_baseurl=http://127.0.0.1:${{ env.PORT }}" dQw4w9WgXcQ 2>&1) || \ + echo "::error title=Failed to run yt-dlp when testing HTTP server::\ + yt-dlp returned $? exit status" + + docker stop bgutil-provider + + echo "::group::Logs from HTTP server container" + docker logs bgutil-provider + echo "::endgroup::" + + echo "::group::Logs from yt-dlp" + printf "%s\n" "$script_response" + echo "::endgroup::" + + if [[ "$script_response" != *"BgUtilHTTPPot: Generating POT via HTTP server"* ]]; then + echo "::error title=BgUtilHTTPPot was not invoked,file=plugin/yt_dlp_plugins/extractor/getpot_bgutil_http.py::\ + BgUtilHTTPPot was not invoked" + exit 1 + fi diff --git a/server/package.json b/server/package.json index e67c0d6..186f6ae 100644 --- a/server/package.json +++ b/server/package.json @@ -18,6 +18,7 @@ "format": "npx prettier --write 'src/**/*.{js,ts}'" }, "dependencies": { + "@commander-js/extra-typings": "commander-js/extra-typings", "bgutils-js": "^1.1.0", "body-parser": "^1.20.2", "commander": "^12.1.0", @@ -26,7 +27,6 @@ "youtubei.js": "^10.4.0" }, "devDependencies": { - "@commander-js/extra-typings": "commander-js/extra-typings", "@eslint/js": "^9.10.0", "@types/express": "^4.17.21", "@types/jsdom": "^21.1.7",