Skip to content
Merged
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
58 changes: 56 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,64 @@ on:
pull_request:
branches: [ master, main, '*.x' ]

# Needed at this level, not only in run_tests.yml: cancelling the reusable workflow's job
# does not cancel this run, so tests-passed would still run, read `cancelled` and publish a
# red aggregator for a push that has already been superseded.
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
Comment thread
mogita marked this conversation as resolved.
tests:
# Skipped on a Release PR: it only bumps the version and rewrites the changelog. Not
# keyed on github.actor, which is the pusher: clicking Update branch reattributes the
# merge commit to whoever clicked, and the skip would stop firing on the normal release
# path. The author and head repo clauses are what make it unforgeable; the branch name
# on its own would let any PR, a fork's included, call its branch release-please--x.
unit:
if: >-
${{ !(github.event.pull_request.user.login == 'github-actions[bot]'
Comment thread
mogita marked this conversation as resolved.
&& github.event.pull_request.head.repo.full_name == github.repository
&& startsWith(github.head_ref, 'release-please--')) }}
uses: ./.github/workflows/run_tests.yml
secrets: inherit

# The one required status check on master. A matrix job skipped by `if:` publishes a
# single check run with the template unexpanded, so per-leg contexts could never be
# satisfied on a Release PR; this job carries no matrix for that reason. `skipped` is
# accepted only when the condition above holds, repeated here because Actions cannot
# share an expression. `!cancelled()` rather than `always()`: a cancelled run must stay
# red, not report a pass.
tests-passed:
name: 🧪 Tests
Comment thread
mogita marked this conversation as resolved.
needs: unit
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Check the unit lane
env:
RESULT: ${{ needs.unit.result }}
RELEASE_PR: >-
${{ github.event.pull_request.user.login == 'github-actions[bot]'
&& github.event.pull_request.head.repo.full_name == github.repository
&& startsWith(github.head_ref, 'release-please--') }}
run: |
case "$RESULT" in
success)
echo "unit lane passed"
;;
skipped)
if [ "$RELEASE_PR" = "true" ]; then
echo "release pr: unit lane skipped by design"
else
echo "::error::the unit lane was skipped on a PR that is not a Release PR"
exit 1
fi
;;
*)
echo "::error::unit lane reported $RESULT"
exit 1
;;
esac
1 change: 0 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ jobs:
needs: detect
if: needs.detect.outputs.ready == 'true'
uses: ./.github/workflows/run_tests.yml
secrets: inherit

# Irreversible half.
release:
Expand Down
117 changes: 117 additions & 0 deletions .github/workflows/run_integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
name: _run-integration

on:
workflow_call:
secrets:
STREAM_API_SECRET:
required: true
STREAM_VIDEO_API_SECRET:
required: true
STREAM_GCP_API_SECRET:
required: false

concurrency:
# Repository-wide, on purpose. The contended resource is the Stream app, not the branch,
# so keying on github.ref would let a *.x release run beside the daily run on master.
# Not `github.workflow` either: inside a reusable workflow that resolves to the caller's
# name. Not cancel-in-progress: a half-run leaves users and channels behind.
group: run-integration
cancel-in-progress: false

permissions:
contents: read

jobs:
integration-chat:
name: 🧪 Chat integration tests
runs-on: ubuntu-latest
timeout-minutes: 30
environment: ci
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.1.0'
bundler-cache: true

- name: Run chat integration tests
env:
STREAM_API_KEY: ${{ vars.STREAM_API_KEY }}
STREAM_API_SECRET: ${{ secrets.STREAM_API_SECRET }}
STREAM_BASE_URL: ${{ vars.STREAM_BASE_URL }}
run: make test-integration-chat

integration-feed:
name: 🧪 Feed integration tests
# Runs after chat rather than beside it: both blank and restore the app-global
# file_upload_config, so in parallel one suite's restore lands mid-assertion in
# the other. !cancelled() keeps the ordering without inheriting the implicit
# success(), so a red chat no longer hides whether feed passes.
needs: integration-chat
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
timeout-minutes: 30
environment: ci
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.1.0'
bundler-cache: true

- name: Run feed integration tests
env:
STREAM_API_KEY: ${{ vars.STREAM_API_KEY }}
STREAM_API_SECRET: ${{ secrets.STREAM_API_SECRET }}
STREAM_BASE_URL: ${{ vars.STREAM_BASE_URL }}
run: make test-integration-feed

integration-video:
name: 🧪 Video integration tests
runs-on: ubuntu-latest
timeout-minutes: 30
environment: ci
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.1.0'
bundler-cache: true

- name: Run video integration tests
env:
STREAM_API_KEY: ${{ vars.STREAM_VIDEO_API_KEY }}
STREAM_API_SECRET: ${{ secrets.STREAM_VIDEO_API_SECRET }}
STREAM_BASE_URL: ${{ vars.STREAM_VIDEO_BASE_URL }}
run: make test-integration-video

integration-gcp-lb:
name: 🧪 GCP load balancer keep-alive
runs-on: ubuntu-latest
timeout-minutes: 30
environment: ci
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.1.0'
bundler-cache: true

- name: Run GCP keep-alive integration test
env:
STREAM_API_KEY: ${{ vars.STREAM_GCP_API_KEY || vars.STREAM_API_KEY }}
STREAM_API_SECRET: ${{ secrets.STREAM_GCP_API_SECRET || secrets.STREAM_API_SECRET }}
STREAM_BASE_URL: ${{ vars.STREAM_GCP_BASE_URL }}
run: make test-integration-gcp-lb
153 changes: 5 additions & 148 deletions .github/workflows/run_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,6 @@ name: _run-tests

on:
workflow_call:
secrets:
STREAM_API_SECRET:
required: true
STREAM_VIDEO_API_SECRET:
required: true
STREAM_GCP_API_SECRET:
required: false

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand All @@ -17,24 +10,12 @@ concurrency:
permissions:
contents: read

# Every job below skips on a Release PR. release-please only bumps the version and rewrites
# the changelog, and every source commit in one already passed this suite on the PR it came
# from. The guard sits on each job rather than on the calling job in ci.yml, because a job
# skipped by `if:` reports success and satisfies a required status check, while a reusable
# workflow that is never called produces no check at all. It tests the author as well as the
# branch name: on its own, the name would let any PR, a fork's included, call its branch
# release-please--x and skip every required check, which branch protection counts as met.
# github.actor is the third clause, and it is the pusher rather than the PR author, so a
# human commit pushed onto the Release PR to fix a conflict or a changelog entry is tested
# like any other commit instead of riding the skip into main untested.
# The unit lane declares no environment and receives no credentials. Keep it that way: a
# fork PR gets no secrets and still goes green, and a live spec added outside
# spec/integration/ fails here instead of passing against someone else's Stream app.
jobs:
unit:
if: >-
${{ !(github.actor == 'github-actions[bot]'
&& github.event.pull_request.user.login == 'github-actions[bot]'
&& github.event.pull_request.head.repo.full_name == github.repository
&& startsWith(github.head_ref, 'release-please--')) }}
name: Unit Tests & Code Quality
name: 🧪 Unit tests & code quality
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
Expand All @@ -45,9 +26,7 @@ jobs:
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.1.0'

- name: Install dependencies
run: bundle install --jobs 4 --retry 3
bundler-cache: true

- name: Run unit tests
run: make test
Expand All @@ -57,125 +36,3 @@ jobs:
make format-check
make lint
make security

integration-chat:
if: >-
${{ !(github.actor == 'github-actions[bot]'
&& github.event.pull_request.user.login == 'github-actions[bot]'
&& github.event.pull_request.head.repo.full_name == github.repository
&& startsWith(github.head_ref, 'release-please--')) }}
name: Chat Integration Tests
runs-on: ubuntu-latest
timeout-minutes: 30
environment: ci
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.1.0'

- name: Install dependencies
run: bundle install --jobs 4 --retry 3

- name: Run chat integration tests
env:
STREAM_API_KEY: ${{ vars.STREAM_API_KEY }}
STREAM_API_SECRET: ${{ secrets.STREAM_API_SECRET }}
STREAM_BASE_URL: ${{ vars.STREAM_BASE_URL }}
run: make test-integration-chat

integration-feed:
name: Feed Integration Tests
# Runs after chat rather than beside it: both blank and restore the app-global
# file_upload_config, so in parallel one suite's restore lands mid-assertion in
# the other. !cancelled() keeps the ordering without inheriting the implicit
# success(), so a red chat no longer hides whether feed passes.
needs: integration-chat
if: >-
${{ !cancelled()
&& !(github.actor == 'github-actions[bot]'
&& github.event.pull_request.user.login == 'github-actions[bot]'
&& github.event.pull_request.head.repo.full_name == github.repository
&& startsWith(github.head_ref, 'release-please--')) }}
runs-on: ubuntu-latest
timeout-minutes: 30
environment: ci
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.1.0'

- name: Install dependencies
run: bundle install --jobs 4 --retry 3

- name: Run feed integration tests
env:
STREAM_API_KEY: ${{ vars.STREAM_API_KEY }}
STREAM_API_SECRET: ${{ secrets.STREAM_API_SECRET }}
STREAM_BASE_URL: ${{ vars.STREAM_BASE_URL }}
run: make test-integration-feed

integration-video:
if: >-
${{ !(github.actor == 'github-actions[bot]'
&& github.event.pull_request.user.login == 'github-actions[bot]'
&& github.event.pull_request.head.repo.full_name == github.repository
&& startsWith(github.head_ref, 'release-please--')) }}
name: Video Integration Tests
runs-on: ubuntu-latest
timeout-minutes: 30
environment: ci
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.1.0'

- name: Install dependencies
run: bundle install --jobs 4 --retry 3

- name: Run video integration tests
env:
STREAM_API_KEY: ${{ vars.STREAM_VIDEO_API_KEY }}
STREAM_API_SECRET: ${{ secrets.STREAM_VIDEO_API_SECRET }}
STREAM_BASE_URL: ${{ vars.STREAM_VIDEO_BASE_URL }}
run: make test-integration-video

integration-gcp-lb:
if: >-
${{ !(github.actor == 'github-actions[bot]'
&& github.event.pull_request.user.login == 'github-actions[bot]'
&& github.event.pull_request.head.repo.full_name == github.repository
&& startsWith(github.head_ref, 'release-please--')) }}
name: GCP load balancer keep-alive
runs-on: ubuntu-latest
timeout-minutes: 30
environment: ci
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.1.0'

- name: Install dependencies
run: bundle install --jobs 4 --retry 3

- name: Run GCP keep-alive integration test
env:
STREAM_API_KEY: ${{ vars.STREAM_GCP_API_KEY || vars.STREAM_API_KEY }}
STREAM_API_SECRET: ${{ secrets.STREAM_GCP_API_SECRET || secrets.STREAM_API_SECRET }}
STREAM_BASE_URL: ${{ vars.STREAM_GCP_BASE_URL }}
run: make test-integration-gcp-lb
Loading
Loading