name: "Spec" on: push: branches: - main tags: - v* pull_request: workflow_dispatch: schedule: # Run this workflow every day at 2am. This helps keep the page of # current spec proposals up-to-date. - cron: '0 2 * * *' jobs: validate-openapi: name: "🔎 Validate OpenAPI specifications" runs-on: ubuntu-latest steps: - name: "📥 Source checkout" uses: actions/checkout@v4 - name: "➕ Setup Node" uses: actions/setup-node@v4 with: node-version: '20' - name: "🔎 Run validator" run: | npx @redocly/cli@latest lint data/api/*/*.yaml check-event-examples: name: "🔎 Check Event schema examples" runs-on: ubuntu-latest steps: - name: "📥 Source checkout" uses: actions/checkout@v4 - name: "➕ Setup Python" uses: actions/setup-python@v5 with: python-version: '3.9' cache: 'pip' cache-dependency-path: scripts/requirements.txt - name: "➕ Install dependencies" run: | pip install -r scripts/requirements.txt - name: "🔎 Run validator" run: | python scripts/check-event-schema-examples.py check-openapi-examples: name: "🔎 Check OpenAPI definitions examples" runs-on: ubuntu-latest steps: - name: "📥 Source checkout" uses: actions/checkout@v4 - name: "➕ Setup Python" uses: actions/setup-python@v5 with: python-version: '3.9' cache: 'pip' cache-dependency-path: scripts/requirements.txt - name: "➕ Install dependencies" run: | pip install -r scripts/requirements.txt - name: "🔎 Run validator" run: | python scripts/check-openapi-sources.py check-schemas-examples: name: "🔎 Check JSON Schemas inline examples" runs-on: ubuntu-latest steps: - name: "📥 Source checkout" uses: actions/checkout@v4 - name: "➕ Setup Python" uses: actions/setup-python@v5 with: python-version: '3.9' cache: 'pip' cache-dependency-path: scripts/requirements.txt - name: "➕ Install dependencies" run: | pip install -r scripts/requirements.txt - name: "🔎 Run validator" run: | python scripts/check-json-schemas.py calculate-baseurl: name: "⚙️ Calculate baseURL for later jobs" runs-on: ubuntu-latest outputs: baseURL: "${{ steps.set-baseurl.outputs.baseURL }}" steps: # For PRs, set the baseURL to `/`. # For releases, set the baseURL to `/$tag` (eg: `/v1.2`). # Otherwise, set it to `/unstable`. - name: "⚙️ Calculate baseURL" id: set-baseurl # Double brackets on the elif to avoid auto-escaping refs/tags/* because we need # the asterisk matching behaviour, not the literal string. run: | if [ "${GITHUB_EVENT_NAME}" == "pull_request" ]; then echo "baseURL=/" >> "$GITHUB_OUTPUT" elif [[ "${GITHUB_REF}" == refs/tags/* ]]; then echo "baseURL=/${GITHUB_REF/refs\/tags\//}" >> "$GITHUB_OUTPUT" else echo "baseURL=/unstable" >> "$GITHUB_OUTPUT" fi build-openapi: name: "🐍 Build OpenAPI definitions" runs-on: ubuntu-latest needs: [calculate-baseurl] steps: - name: "📥 Source checkout" uses: actions/checkout@v4 - name: "➕ Setup Python" uses: actions/setup-python@v5 with: python-version: '3.9' cache: 'pip' cache-dependency-path: scripts/requirements.txt - name: "➕ Install dependencies" run: | pip install -r scripts/requirements.txt - name: "📦 Asset creation" run: | if [[ "${GITHUB_REF}" == refs/tags/* ]]; then export RELEASE="${GITHUB_REF/refs\/tags\//}" else export RELEASE="unstable" fi # The output path matches the final deployment path at spec.matrix.org scripts/dump-openapi.py \ --base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \ --api application-service \ -r "$RELEASE" \ -o spec/application-service-api/api.json scripts/dump-openapi.py \ --base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \ --api client-server \ -r "$RELEASE" \ -o spec/client-server-api/api.json scripts/dump-openapi.py \ --base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \ --api push-gateway \ -r "$RELEASE" \ -o spec/push-gateway-api/api.json scripts/dump-openapi.py \ --base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \ --api server-server \ -r "$RELEASE" \ -o spec/server-server-api/api.json tar -czf openapi.tar.gz spec - name: "📤 Artifact upload" uses: actions/upload-artifact@v4 with: name: openapi-artifact path: openapi.tar.gz generate-changelog: name: "📢 Run towncrier for changelog" # skip for builds of git tags if: "!startsWith(github.ref, 'refs/tags/')" runs-on: ubuntu-latest steps: - name: "📥 Source checkout" uses: actions/checkout@v4 - name: "➕ Setup Python" uses: actions/setup-python@v5 with: python-version: '3.9' - name: "➕ Install towncrier" run: "pip install 'towncrier'" - name: "Generate changelog" run: ./scripts/generate-changelog.sh vUNSTABLE - name: "📤 Artifact upload" uses: actions/upload-artifact@v4 with: name: changelog-artifact path: content/changelog/unstable.md build-spec: name: "📖 Build the spec" runs-on: ubuntu-latest needs: [calculate-baseurl, build-openapi, generate-changelog] # run even if generate-changelog was skipped if: ${{ always() }} steps: - name: "➕ Setup Node" uses: actions/setup-node@v4 with: node-version: '20' - name: "➕ Setup Hugo" uses: peaceiris/actions-hugo@75d2e84710de30f6ff7268e08f310b60ef14033f # v3.0.0 with: hugo-version: '0.117.0' extended: true - name: "📥 Source checkout" uses: actions/checkout@v4 - name: "⚙️ npm" run: | npm i npm run get-proposals - name: "📥 Download generated changelog" if: "needs.generate-changelog.result == 'success'" uses: actions/download-artifact@v4 with: name: changelog-artifact path: content/changelog - name: "⚙️ hugo" run: hugo --baseURL "${{ needs.calculate-baseurl.outputs.baseURL }}" -d "spec" # We manually unpack the spec OpenAPI definition JSON to the website tree # to make it available to the world in a canonical place: # https://spec.matrix.org/latest/client-server-api/api.json # Works for /unstable/ and /v1.1/ as well. - name: "📥 Spec definition download" uses: actions/download-artifact@v4 with: name: openapi-artifact - name: "📝 Unpack the OpenAPI definitions in the right location" run: | tar -xzf openapi.tar.gz - name: "📦 Tarball creation" run: tar -czf spec.tar.gz spec - name: "📤 Artifact upload" uses: actions/upload-artifact@v4 with: name: spec-artifact path: spec.tar.gz htmlcheck: name: "🔎 Validate generated HTML" runs-on: ubuntu-latest needs: [calculate-baseurl, build-spec] steps: - name: "📥 Source checkout" uses: actions/checkout@v4 - name: "📥 Fetch built spec" uses: actions/download-artifact@v4 with: name: spec-artifact - name: "📝 Unpack the spec" # we have to unpack it into the right path given the baseurl, so that the # links are correct. # eg if baseurl is `/unstable`, we want to put the site in `spec/unstable`. run: | mkdir -p "spec${baseURL}" tar -C "spec${baseURL}" --strip-components=1 -xvzf spec.tar.gz env: baseURL: "${{ needs.calculate-baseurl.outputs.baseURL }}" - name: "Run htmltest" uses: wjdp/htmltest-action@master with: config: .htmltest.yaml build-historical-spec: name: "📖 Build the historical backup spec" runs-on: ubuntu-latest needs: [build-openapi] if: ${{ startsWith(github.ref, 'refs/tags/') }} steps: - name: "➕ Setup Node" uses: actions/setup-node@v4 with: node-version: '20' - name: "➕ Setup Hugo" uses: peaceiris/actions-hugo@75d2e84710de30f6ff7268e08f310b60ef14033f # v3.0.0 with: # Cannot build the spec with Hugo 0.125.0 because of https://github.com/google/docsy/issues/1930 hugo-version: '0.124.1' extended: true - name: "📥 Source checkout" uses: actions/checkout@v4 - name: "⚙️ npm" run: | npm i npm run get-proposals - name: "⚙️ hugo" # Create a baseURL like `/v1.2` out of the `v1.2` tag run: | echo -e '[params.version]\nstatus="historical"' > historical.toml hugo --config config.toml,historical.toml --baseURL "/${GITHUB_REF/refs\/tags\//}" -d "spec" - name: "📥 Spec definition download" uses: actions/download-artifact@v4 with: name: openapi-artifact - name: "📝 Unpack the OpenAPI definitions in the right location" run: | tar -xzf openapi.tar.gz - name: "📦 Tarball creation" run: tar -czf spec-historical.tar.gz spec - name: "📤 Artifact upload" uses: actions/upload-artifact@v4 with: name: spec-historical-artifact path: spec-historical.tar.gz