From 81adcf107bb20c0563db34f7bf6f8faff838beb8 Mon Sep 17 00:00:00 2001 From: John Coffey Date: Mon, 5 Oct 2026 22:07:52 -0700 Subject: [PATCH] Add the coffeylabs theme and the image build The coffeylabs theme brings coffeylabs.org's palette, type and blueprint grid to Mastodon. It loads the stock stylesheet and then overrides Mastodon's color tokens for both color schemes, adds Bricolage Grotesque and JetBrains Mono (OFL, served from the instance), and replaces the navigation wordmark. The default theme stays available to users. Small upstream changes, each with a modification notice: themes.yml registers the theme, themes.rb sets the dark browser-bar color, and the Dockerfile takes SOURCE_BASE_URL and SOURCE_TAG so "View source code" points at this repository, as the AGPL expects. Upstream's GitHub workflows are removed. .gitea/workflows/ci.yml builds the image on every change and publishes it, with a release, from tags named v-coffeylabs.. COFFEYLABS.md lists every change. --- .gitea/workflows/ci.yml | 113 +++++ .github/workflows/build-container-image.yml | 171 -------- .github/workflows/build-nightly.yml | 62 --- .github/workflows/build-push-pr.yml | 58 --- .github/workflows/build-releases.yml | 84 ---- .github/workflows/build-security.yml | 59 --- .github/workflows/bundler-audit.yml | 40 -- .github/workflows/check-i18n.yml | 52 --- .github/workflows/chromatic.yml | 64 --- .github/workflows/codeql.yml | 67 --- .github/workflows/crowdin-download-stable.yml | 69 ---- .github/workflows/crowdin-download.yml | 71 ---- .github/workflows/crowdin-upload.yml | 38 -- .github/workflows/format-check.yml | 23 -- .github/workflows/lint-css.yml | 40 -- .github/workflows/lint-haml.yml | 44 -- .github/workflows/lint-js.yml | 49 --- .github/workflows/lint-ruby.yml | 49 --- .github/workflows/rebase-needed.yml | 28 -- .github/workflows/test-image-build.yml | 34 -- .github/workflows/test-js.yml | 44 -- .github/workflows/test-migrations.yml | 113 ----- .github/workflows/test-ruby.yml | 390 ------------------ COFFEYLABS.md | 43 ++ Dockerfile | 9 + .../fonts/coffeylabs/OFL-bricolage.txt | 93 +++++ .../fonts/coffeylabs/OFL-jetbrains-mono.txt | 93 +++++ ...ricolage-grotesque-latin-wght-normal.woff2 | Bin 0 -> 41344 bytes .../jetbrains-mono-latin-wght-normal.woff2 | Bin 0 -> 40404 bytes app/javascript/styles/coffeylabs.scss | 7 + app/javascript/styles/coffeylabs/_fonts.scss | 32 ++ .../styles/coffeylabs/_palette.scss | 89 ++++ .../styles/coffeylabs/_surfaces.scss | 108 +++++ app/lib/themes.rb | 5 +- config/themes.yml | 2 + 35 files changed, 593 insertions(+), 1650 deletions(-) create mode 100644 .gitea/workflows/ci.yml delete mode 100644 .github/workflows/build-container-image.yml delete mode 100644 .github/workflows/build-nightly.yml delete mode 100644 .github/workflows/build-push-pr.yml delete mode 100644 .github/workflows/build-releases.yml delete mode 100644 .github/workflows/build-security.yml delete mode 100644 .github/workflows/bundler-audit.yml delete mode 100644 .github/workflows/check-i18n.yml delete mode 100644 .github/workflows/chromatic.yml delete mode 100644 .github/workflows/codeql.yml delete mode 100644 .github/workflows/crowdin-download-stable.yml delete mode 100644 .github/workflows/crowdin-download.yml delete mode 100644 .github/workflows/crowdin-upload.yml delete mode 100644 .github/workflows/format-check.yml delete mode 100644 .github/workflows/lint-css.yml delete mode 100644 .github/workflows/lint-haml.yml delete mode 100644 .github/workflows/lint-js.yml delete mode 100644 .github/workflows/lint-ruby.yml delete mode 100644 .github/workflows/rebase-needed.yml delete mode 100644 .github/workflows/test-image-build.yml delete mode 100644 .github/workflows/test-js.yml delete mode 100644 .github/workflows/test-migrations.yml delete mode 100644 .github/workflows/test-ruby.yml create mode 100644 COFFEYLABS.md create mode 100644 app/javascript/fonts/coffeylabs/OFL-bricolage.txt create mode 100644 app/javascript/fonts/coffeylabs/OFL-jetbrains-mono.txt create mode 100644 app/javascript/fonts/coffeylabs/bricolage-grotesque-latin-wght-normal.woff2 create mode 100644 app/javascript/fonts/coffeylabs/jetbrains-mono-latin-wght-normal.woff2 create mode 100644 app/javascript/styles/coffeylabs.scss create mode 100644 app/javascript/styles/coffeylabs/_fonts.scss create mode 100644 app/javascript/styles/coffeylabs/_palette.scss create mode 100644 app/javascript/styles/coffeylabs/_surfaces.scss diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..9b0002d --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,113 @@ +# CI for the Coffey Labs build of Mastodon: upstream Mastodon plus the +# coffeylabs theme (COFFEYLABS.md). Upstream's own .github/workflows were +# removed in this fork; this is the only workflow, and it runs on Gitea only. +# +# Every change builds the image without pushing it, to prove the theme still +# compiles against the upstream it sits on. Releases are cut by pushing a tag +# named v-coffeylabs., e.g. v4.7.3-coffeylabs.1, where +# is the version in lib/mastodon/version.rb. The tag must name the commit's +# own upstream version and be on main, or nothing is published. +# +# Every job runs in an image pinned by digest (tag in the trailing comment), +# and the only action used is coffey-labs/actions/checkout pinned by SHA. +# Read the comment for the version; the digest is what runs. +name: ci + +on: + push: + branches: [main] + tags: ['v*-coffeylabs.*'] + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + # ------------------------------------------------------------- build ------ + # The full production image, as the Dockerfile builds it: Ruby gems, the + # Vite asset build with both themes, libvips and ffmpeg. Nothing is pushed. + docker-build: + if: ${{ !startsWith(github.ref, 'refs/tags/') }} + runs-on: docker + timeout-minutes: 90 + container: + image: docker:28-cli@sha256:625d9431a9f54c5a2bc90f24f0e1c3d55b1349fd857dd85035f98c2c9acbdd4d # 28-cli + volumes: + - /var/run/docker.sock:/var/run/docker.sock + steps: + - uses: coffey-labs/actions/checkout@fab0c4d45e0162963965f1555df27b7bed5e20ec + - run: | + tag="mastodon:ci-$(echo "$GITHUB_SHA" | cut -c1-8)" + docker build --build-arg MASTODON_VERSION_METADATA=coffeylabs.ci -t "$tag" . + docker run --rm --entrypoint sh "$tag" -c \ + 'ls public/packs/assets/themes/ | grep -q "^coffeylabs-.*\.css$"' \ + || { echo "!! the image has no compiled coffeylabs theme" >&2; exit 1; } + docker image rm "$tag" + + # ----------------------------------------------------------- release ------ + # linux/amd64 only: the one server that runs it is amd64. The streaming + # server is unchanged by the theme, so it keeps using upstream's image at + # the same version. PACKAGE_TOKEN (jcoffey-dev, write:package) logs in: the + # job's own token is refused by the container registry. The release is + # created last, so a release on the page always has its image behind it. + publish: + if: ${{ startsWith(github.ref, 'refs/tags/v') }} + runs-on: docker + timeout-minutes: 90 + container: + image: docker:28-cli@sha256:625d9431a9f54c5a2bc90f24f0e1c3d55b1349fd857dd85035f98c2c9acbdd4d # 28-cli + volumes: + - /var/run/docker.sock:/var/run/docker.sock + env: + REGISTRY: ${{ vars.REGISTRY }} + IMAGE: ${{ vars.REGISTRY }}/${{ github.repository }} + TAG: ${{ github.ref_name }} + PACKAGE_TOKEN: ${{ secrets.PACKAGE_TOKEN }} + steps: + - uses: coffey-labs/actions/checkout@fab0c4d45e0162963965f1555df27b7bed5e20ec + with: + fetch-depth: 0 + - id: v + run: | + set -eu + upstream="$(awk '/def (major|minor|patch)$/ { getline; gsub(/ /, ""); printf "%s%s", sep, $0; sep="." }' lib/mastodon/version.rb)" + case "$TAG" in + "v$upstream-coffeylabs."[0-9]*) ;; + *) echo "!! $TAG does not name this commit's upstream version; expected v$upstream-coffeylabs." >&2; exit 1 ;; + esac + git merge-base --is-ancestor "$(git rev-parse "${TAG}^{commit}")" origin/main \ + || { echo "!! $TAG is not on main" >&2; exit 1; } + echo "METADATA=${TAG#v"$upstream"-}" >> "$GITHUB_OUTPUT" + - run: | + test -n "$REGISTRY" + test -n "$PACKAGE_TOKEN" || { echo "PACKAGE_TOKEN secret is not set on this repository" >&2; exit 1; } + echo "$PACKAGE_TOKEN" | docker login -u jcoffey-dev --password-stdin "$REGISTRY" + - env: + METADATA: ${{ steps.v.outputs.METADATA }} + run: | + docker build \ + --build-arg MASTODON_VERSION_METADATA="$METADATA" \ + --build-arg SOURCE_COMMIT="$GITHUB_SHA" \ + --build-arg SOURCE_BASE_URL="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY" \ + --build-arg SOURCE_TAG="$TAG" \ + --tag "$IMAGE:$TAG" . + docker push "$IMAGE:$TAG" + docker image rm "$IMAGE:$TAG" + # Show the package on the repository's Packages tab. Idempotent. + - run: | + apk add --no-cache -q curl + curl -fsS -o /dev/null -X POST -H "Authorization: token $PACKAGE_TOKEN" \ + "$CI_SERVER_INTERNAL/api/v1/packages/${GITHUB_REPOSITORY%%/*}/container/${GITHUB_REPOSITORY#*/}/-/link/${GITHUB_REPOSITORY#*/}" \ + || echo "package already linked (or link refused); not fatal" + - env: + TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -eu + body="Mastodon ${TAG%-coffeylabs.*} with the coffeylabs theme.\n\nImage: \`$IMAGE:$TAG\` (linux/amd64). Use upstream's mastodon-streaming image at ${TAG%-coffeylabs.*}." + curl -fsS -o /dev/null -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \ + --data "{\"tag_name\":\"$TAG\",\"name\":\"$TAG\",\"body\":\"$body\"}" \ + "$CI_SERVER_INTERNAL/api/v1/repos/$GITHUB_REPOSITORY/releases" + echo "release $TAG created" + - if: always() + run: docker logout "$REGISTRY" || true diff --git a/.github/workflows/build-container-image.yml b/.github/workflows/build-container-image.yml deleted file mode 100644 index 7924655..0000000 --- a/.github/workflows/build-container-image.yml +++ /dev/null @@ -1,171 +0,0 @@ -on: - workflow_call: - inputs: - cache: - type: boolean - default: true - push_to_images: - type: string - version_prerelease: - type: string - version_metadata: - type: string - flavor: - type: string - tags: - type: string - labels: - type: string - file_to_build: - type: string - -# This builds multiple images with one runner each, allowing us to build for multiple architectures -# using Github's runners. -# The two-step process is adapted form: -# https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners -jobs: - # Build each (amd64 and arm64) image separately - build-image: - runs-on: ${{ startsWith(matrix.platform, 'linux/arm') && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }} - strategy: - fail-fast: false - matrix: - platform: - - linux/amd64 - - linux/arm64 - - steps: - - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - name: Prepare - env: - PUSH_TO_IMAGES: ${{ inputs.push_to_images }} - run: | - platform=${{ matrix.platform }} - echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - # Transform multi-line variable into comma-separated variable - image_names=${PUSH_TO_IMAGES//$'\n'/,} - image_names_split=${image_names%,} - echo "IMAGE_NAMES=${image_names_split,,}" >> $GITHUB_ENV - - - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 - id: buildx - - - name: Log in to Docker Hub - if: contains(inputs.push_to_images, 'tootsuite') - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Log in to the GitHub Container registry - if: contains(inputs.push_to_images, 'ghcr.io') - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Docker meta - id: meta - uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5 - if: ${{ inputs.push_to_images != '' }} - with: - images: ${{ inputs.push_to_images }} - flavor: ${{ inputs.flavor }} - labels: ${{ inputs.labels }} - - - name: Build and push by digest - id: build - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 - with: - context: . - file: ${{ inputs.file_to_build }} - build-args: | - MASTODON_VERSION_PRERELEASE=${{ inputs.version_prerelease }} - MASTODON_VERSION_METADATA=${{ inputs.version_metadata }} - SOURCE_COMMIT=${{ github.sha }} - platforms: ${{ matrix.platform }} - provenance: false - push: ${{ inputs.push_to_images != '' }} - cache-from: ${{ inputs.cache && format('type=gha,scope=build-{0}-{1}', hashFiles(inputs.file_to_build), env.PLATFORM_PAIR) || '' }} - cache-to: ${{ inputs.cache && format('type=gha,mode=max,scope=build-{0}-{1}', hashFiles(inputs.file_to_build), env.PLATFORM_PAIR) || '' }} - outputs: type=image,"name=${{ env.IMAGE_NAMES }}",push-by-digest=true,name-canonical=true,push=${{ inputs.push_to_images != '' }} - - - name: Export digest - if: ${{ inputs.push_to_images != '' }} - run: | - mkdir -p "${{ runner.temp }}/digests" - digest="${{ steps.build.outputs.digest }}" - touch "${{ runner.temp }}/digests/${digest#sha256:}" - - - name: Upload digest - if: ${{ inputs.push_to_images != '' }} - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - # `hashFiles` is used to disambiguate between streaming and non-streaming images - name: digests-${{ hashFiles(inputs.file_to_build) }}-${{ env.PLATFORM_PAIR }} - path: ${{ runner.temp }}/digests/* - if-no-files-found: error - retention-days: 1 - - # Then merge the docker images into a single one - merge-images: - if: ${{ inputs.push_to_images != '' }} - runs-on: ubuntu-24.04 - needs: - - build-image - - env: - PUSH_TO_IMAGES: ${{ inputs.push_to_images }} - - steps: - - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - name: Download digests - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 - with: - path: ${{ runner.temp }}/digests - # `hashFiles` is used to disambiguate between streaming and non-streaming images - pattern: digests-${{ hashFiles(inputs.file_to_build) }}-* - merge-multiple: true - - - name: Log in to Docker Hub - if: contains(inputs.push_to_images, 'tootsuite') - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Log in to the GitHub Container registry - if: contains(inputs.push_to_images, 'ghcr.io') - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 - - - name: Docker meta - id: meta - uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5 - if: ${{ inputs.push_to_images != '' }} - with: - images: ${{ inputs.push_to_images }} - flavor: ${{ inputs.flavor }} - tags: ${{ inputs.tags }} - labels: ${{ inputs.labels }} - - - name: Create manifest list and push - working-directory: ${{ runner.temp }}/digests - run: | - echo "${PUSH_TO_IMAGES,,}" | xargs -I{} \ - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '{}@sha256:%s ' *) - - - name: Inspect image - run: | - echo "${PUSH_TO_IMAGES,,}" | xargs -i{} \ - docker buildx imagetools inspect {}:${{ steps.meta.outputs.version }} diff --git a/.github/workflows/build-nightly.yml b/.github/workflows/build-nightly.yml deleted file mode 100644 index 4a56f72..0000000 --- a/.github/workflows/build-nightly.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: Build nightly container image -on: - workflow_dispatch: - schedule: - - cron: '0 2 * * *' # run at 2 AM UTC - -permissions: - contents: read - packages: write - -jobs: - compute-suffix: - runs-on: ubuntu-latest - if: github.repository == 'mastodon/mastodon' - steps: - - id: version_vars - env: - TZ: Etc/UTC - run: | - echo mastodon_version_prerelease=nightly.$(date +'%Y-%m-%d')>> $GITHUB_OUTPUT - outputs: - prerelease: ${{ steps.version_vars.outputs.mastodon_version_prerelease }} - - build-image: - needs: compute-suffix - uses: ./.github/workflows/build-container-image.yml - with: - file_to_build: Dockerfile - cache: false - push_to_images: | - tootsuite/mastodon - ghcr.io/mastodon/mastodon - version_prerelease: ${{ needs.compute-suffix.outputs.prerelease }} - labels: | - org.opencontainers.image.description=Nightly build image used for testing purposes - flavor: | - latest=auto - tags: | - type=raw,value=edge - type=raw,value=nightly - type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }} - secrets: inherit - - build-image-streaming: - needs: compute-suffix - uses: ./.github/workflows/build-container-image.yml - with: - file_to_build: streaming/Dockerfile - cache: false - push_to_images: | - tootsuite/mastodon-streaming - ghcr.io/mastodon/mastodon-streaming - version_prerelease: ${{ needs.compute-suffix.outputs.prerelease }} - labels: | - org.opencontainers.image.description=Nightly build image used for testing purposes - flavor: | - latest=auto - tags: | - type=raw,value=edge - type=raw,value=nightly - type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }} - secrets: inherit diff --git a/.github/workflows/build-push-pr.yml b/.github/workflows/build-push-pr.yml deleted file mode 100644 index f55012b..0000000 --- a/.github/workflows/build-push-pr.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Build container image for PR -on: - pull_request: - types: [labeled, synchronize, reopened, ready_for_review, opened] - -permissions: - contents: read - packages: write - -jobs: - compute-suffix: - runs-on: ubuntu-latest - # This is only allowed to run if: - # - the PR branch is in the `mastodon/mastodon` repository - # - the PR is not a draft - # - the PR has the "build-image" label - if: ${{ github.event.pull_request.head.repo.full_name == github.repository && !github.event.pull_request.draft && contains(github.event.pull_request.labels.*.name, 'build-image') }} - steps: - # Repository needs to be cloned so `git rev-parse` below works - - name: Clone repository - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - id: version_vars - run: | - echo mastodon_version_metadata=pr-${{ github.event.pull_request.number }}-$(git rev-parse --short ${{github.event.pull_request.head.sha}}) >> $GITHUB_OUTPUT - echo mastodon_short_sha=$(git rev-parse --short ${{github.event.pull_request.head.sha}}) >> $GITHUB_OUTPUT - outputs: - metadata: ${{ steps.version_vars.outputs.mastodon_version_metadata }} - short_sha: ${{ steps.version_vars.outputs.mastodon_short_sha }} - - build-image: - needs: compute-suffix - uses: ./.github/workflows/build-container-image.yml - with: - file_to_build: Dockerfile - push_to_images: | - ghcr.io/mastodon/mastodon - version_metadata: ${{ needs.compute-suffix.outputs.metadata }} - flavor: | - latest=auto - tags: | - type=ref,event=pr - type=ref,event=pr,suffix=-${{ needs.compute-suffix.outputs.short_sha }} - secrets: inherit - - build-image-streaming: - needs: compute-suffix - uses: ./.github/workflows/build-container-image.yml - with: - file_to_build: streaming/Dockerfile - push_to_images: | - ghcr.io/mastodon/mastodon-streaming - version_metadata: ${{ needs.compute-suffix.outputs.metadata }} - flavor: | - latest=auto - tags: | - type=ref,event=pr - type=ref,event=pr,suffix=-${{ needs.compute-suffix.outputs.short_sha }} - secrets: inherit diff --git a/.github/workflows/build-releases.yml b/.github/workflows/build-releases.yml deleted file mode 100644 index c8e0925..0000000 --- a/.github/workflows/build-releases.yml +++ /dev/null @@ -1,84 +0,0 @@ -name: Build container release images -on: - push: - tags: - - '*' - -permissions: - contents: read - packages: write - -jobs: - check-latest-stable: - runs-on: ubuntu-latest - outputs: - latest: ${{ steps.check.outputs.is_latest_stable }} - steps: - # Repository needs to be cloned to list branches - - name: Clone repository - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - with: - fetch-depth: 0 - - - name: Check latest stable - shell: bash - id: check - run: | - ref="${GITHUB_REF#refs/tags/}" - - if [[ "$ref" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?$ ]]; then - current="${BASH_REMATCH[1]}.${BASH_REMATCH[2]}" - else - echo "tag $ref is not semver" - echo "is_latest_stable=false" >> "$GITHUB_OUTPUT" - exit 0 - fi - - latest=$(git for-each-ref --format='%(refname:short)' "refs/remotes/origin/stable-*.*" \ - | sed -E 's#^origin/stable-##' \ - | sort -Vr \ - | head -n1) - - if [[ "$current" == "$latest" ]]; then - echo "is_latest_stable=true" >> "$GITHUB_OUTPUT" - else - echo "is_latest_stable=false" >> "$GITHUB_OUTPUT" - fi - - build-image: - needs: check-latest-stable - uses: ./.github/workflows/build-container-image.yml - with: - file_to_build: Dockerfile - push_to_images: | - tootsuite/mastodon - ghcr.io/mastodon/mastodon - # Do not use cache when building releases, so apt update is always ran and the release always contain the latest packages - cache: false - # Only tag with latest when ran against the latest stable branch - # This needs to be updated after each minor version release - flavor: | - latest=${{ needs.check-latest-stable.outputs.latest }} - tags: | - type=pep440,pattern={{raw}} - type=pep440,pattern=v{{major}}.{{minor}} - secrets: inherit - - build-image-streaming: - needs: check-latest-stable - uses: ./.github/workflows/build-container-image.yml - with: - file_to_build: streaming/Dockerfile - push_to_images: | - tootsuite/mastodon-streaming - ghcr.io/mastodon/mastodon-streaming - # Do not use cache when building releases, so apt update is always ran and the release always contain the latest packages - cache: false - # Only tag with latest when ran against the latest stable branch - # This needs to be updated after each minor version release - flavor: | - latest=${{ needs.check-latest-stable.outputs.latest }} - tags: | - type=pep440,pattern={{raw}} - type=pep440,pattern=v{{major}}.{{minor}} - secrets: inherit diff --git a/.github/workflows/build-security.yml b/.github/workflows/build-security.yml deleted file mode 100644 index 72729b5..0000000 --- a/.github/workflows/build-security.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Build security nightly container image -on: - workflow_dispatch: - -permissions: - contents: read - packages: write - -jobs: - compute-suffix: - runs-on: ubuntu-latest - steps: - - id: version_vars - env: - TZ: Etc/UTC - run: | - echo mastodon_version_prerelease=nightly.$(date --date='next day' +'%Y-%m-%d')-security>> $GITHUB_OUTPUT - outputs: - prerelease: ${{ steps.version_vars.outputs.mastodon_version_prerelease }} - - build-image: - needs: compute-suffix - uses: ./.github/workflows/build-container-image.yml - with: - file_to_build: Dockerfile - cache: false - push_to_images: | - tootsuite/mastodon - ghcr.io/mastodon/mastodon - version_prerelease: ${{ needs.compute-suffix.outputs.prerelease }} - labels: | - org.opencontainers.image.description=Nightly build image used for testing purposes - flavor: | - latest=auto - tags: | - type=raw,value=edge - type=raw,value=nightly - type=raw,value=${{ needs.compute-suffix.outputs.prerelease }} - secrets: inherit - - build-image-streaming: - needs: compute-suffix - uses: ./.github/workflows/build-container-image.yml - with: - file_to_build: streaming/Dockerfile - cache: false - push_to_images: | - tootsuite/mastodon-streaming - ghcr.io/mastodon/mastodon-streaming - version_prerelease: ${{ needs.compute-suffix.outputs.prerelease }} - labels: | - org.opencontainers.image.description=Nightly build image used for testing purposes - flavor: | - latest=auto - tags: | - type=raw,value=edge - type=raw,value=nightly - type=raw,value=${{ needs.compute-suffix.outputs.prerelease }} - secrets: inherit diff --git a/.github/workflows/bundler-audit.yml b/.github/workflows/bundler-audit.yml deleted file mode 100644 index b51f792..0000000 --- a/.github/workflows/bundler-audit.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Bundler Audit -on: - merge_group: - push: - branches: - - 'main' - - 'stable-*' - paths: - - 'Gemfile*' - - '.ruby-version' - - '.github/workflows/bundler-audit.yml' - - pull_request: - paths: - - 'Gemfile*' - - '.ruby-version' - - '.github/workflows/bundler-audit.yml' - - schedule: - - cron: '0 5 * * 1' - -jobs: - security: - runs-on: ubuntu-latest - timeout-minutes: 15 - - env: - BUNDLE_ONLY: development - - steps: - - name: Clone repository - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - name: Set up Ruby - uses: ruby/setup-ruby@6e5d382445ae5590b7449d8b3bc8cb1c2c27f617 # v1 - with: - bundler-cache: true - - - name: Run bundler-audit - run: bin/bundler-audit check --update diff --git a/.github/workflows/check-i18n.yml b/.github/workflows/check-i18n.yml deleted file mode 100644 index bd77ec5..0000000 --- a/.github/workflows/check-i18n.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: Check i18n - -on: - push: - branches: - - 'main' - - 'stable-*' - pull_request: - branches: - - 'main' - - 'stable-*' - -env: - RAILS_ENV: test - -permissions: - contents: read - -jobs: - check-i18n: - runs-on: ubuntu-latest - timeout-minutes: 15 - - steps: - - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - name: Set up Ruby environment - uses: ./.github/actions/setup-ruby - - - name: Set up Javascript environment - uses: ./.github/actions/setup-javascript - - - name: Check for missing strings in English JSON - run: | - yarn i18n:extract --throws - git diff --exit-code - - - name: Check locale file normalization - run: bin/i18n-tasks check-normalized - - - name: Check for unused strings - run: bin/i18n-tasks unused -l en - - - name: Check for missing strings in English YML - run: | - bin/i18n-tasks missing -t used -l en - - - name: Check for wrong string interpolations - run: bin/i18n-tasks check-consistent-interpolations - - - name: Check that all required locale files exist - run: bin/rake repo:check_locales_files diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml deleted file mode 100644 index 0068fc2..0000000 --- a/.github/workflows/chromatic.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: 'Chromatic' -permissions: - contents: read - -on: - push: - branches-ignore: - - renovate/* - - stable-* - -jobs: - pathcheck: - name: Check for relevant changes - runs-on: ubuntu-latest - timeout-minutes: 15 - outputs: - changed: ${{ steps.filter.outputs.src }} - steps: - - name: Checkout code - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - with: - fetch-depth: 0 - - - uses: dorny/paths-filter@0e4a8c6effa4802afeda77dc8d303f8176d7dfad # v3 - id: filter - with: - filters: | - src: - - 'package.json' - - 'yarn.lock' - - '**/*.js' - - '**/*.jsx' - - '**/*.ts' - - '**/*.tsx' - - '**/*.css' - - '**/*.scss' - - '.github/workflows/chromatic.yml' - - chromatic: - name: Run Chromatic - runs-on: ubuntu-latest - timeout-minutes: 15 - needs: pathcheck - if: github.repository == 'mastodon/mastodon' && needs.pathcheck.outputs.changed == 'true' - steps: - - name: Checkout code - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - with: - fetch-depth: 0 - - - name: Set up Javascript environment - uses: ./.github/actions/setup-javascript - - - name: Build Storybook - run: yarn build-storybook - - - name: Run Chromatic - uses: chromaui/action@98132da0fca2211fb41b3af7b49ce85176007851 # v17 - with: - projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} - zip: true - storybookBuildDir: 'storybook-static' - exitOnceUploaded: true # Exit immediately after upload - autoAcceptChanges: 'main' # Auto-accept changes on main branch only diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index fea0b46..0000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,67 +0,0 @@ -name: 'CodeQL' - -on: - merge_group: - push: - branches: - - 'main' - - 'stable-*' - pull_request: - branches: - - 'main' - - 'stable-*' - schedule: - - cron: '22 6 * * 1' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - timeout-minutes: 15 - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: ['actions', 'javascript', 'ruby'] - # CodeQL supports [ 'actions', 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] - # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support - - steps: - - name: Checkout repository - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - - # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@5595ccaf912efad79be6eef63a5619ff05969be3 # v4 - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4 - with: - category: '/language:${{matrix.language}}' diff --git a/.github/workflows/crowdin-download-stable.yml b/.github/workflows/crowdin-download-stable.yml deleted file mode 100644 index 2eef46f..0000000 --- a/.github/workflows/crowdin-download-stable.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: Crowdin / Download translations (stable branches) -on: - workflow_dispatch: - -permissions: - contents: write - pull-requests: write - -jobs: - download-translations-stable: - runs-on: ubuntu-latest - if: github.repository == 'mastodon/mastodon' - - steps: - - name: Checkout - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - name: Increase Git http.postBuffer - # This is needed due to a bug in Ubuntu's cURL version? - # See https://github.com/orgs/community/discussions/55820 - run: | - git config --global http.version HTTP/1.1 - git config --global http.postBuffer 157286400 - - # Download the translation files from Crowdin - - name: crowdin action - uses: crowdin/github-action@c7af9bc98b01694653031fef2a0dc6c7888ce9bc # v2 - with: - upload_sources: false - upload_translations: false - download_translations: true - crowdin_branch_name: ${{ github.base_ref || github.ref_name }} - push_translations: false - create_pull_request: false - env: - CROWDIN_PROJECT_ID: ${{ vars.CROWDIN_PROJECT_ID }} - CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} - - # As the files are extracted from a Docker container, they belong to root:root - # We need to fix this before the next steps - - name: Fix file permissions - run: sudo chown -R runner:docker . - - # This is needed to run the normalize step - - name: Set up Ruby environment - uses: ./.github/actions/setup-ruby - - - name: Run i18n normalize task - run: bin/i18n-tasks normalize - - # Create or update the pull request - - name: Create Pull Request - uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 - with: - commit-message: 'New Crowdin translations' - title: 'New Crowdin Translations for ${{ github.base_ref || github.ref_name }} (automated)' - author: 'GitHub Actions ' - body: | - New Crowdin translations, automated with GitHub Actions - - See `.github/workflows/crowdin-download.yml` - - This PR will be updated every day with new translations. - - Due to a limitation in GitHub Actions, checks are not running on this PR without manual action. - If you want to run the checks, then please press “Approve workflows to run”. - branch: i18n/crowdin/translations-${{ github.base_ref || github.ref_name }} - base: ${{ github.base_ref || github.ref_name }} - labels: i18n diff --git a/.github/workflows/crowdin-download.yml b/.github/workflows/crowdin-download.yml deleted file mode 100644 index e221fd6..0000000 --- a/.github/workflows/crowdin-download.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: Crowdin / Download translations -on: - schedule: - - cron: '17 4 * * *' # Every day - workflow_dispatch: - -permissions: - contents: write - pull-requests: write - -jobs: - download-translations: - runs-on: ubuntu-latest - if: github.repository == 'mastodon/mastodon' - - steps: - - name: Checkout - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - name: Increase Git http.postBuffer - # This is needed due to a bug in Ubuntu's cURL version? - # See https://github.com/orgs/community/discussions/55820 - run: | - git config --global http.version HTTP/1.1 - git config --global http.postBuffer 157286400 - - # Download the translation files from Crowdin - - name: crowdin action - uses: crowdin/github-action@c7af9bc98b01694653031fef2a0dc6c7888ce9bc # v2 - with: - upload_sources: false - upload_translations: false - download_translations: true - crowdin_branch_name: main - push_translations: false - create_pull_request: false - env: - CROWDIN_PROJECT_ID: ${{ vars.CROWDIN_PROJECT_ID }} - CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} - - # As the files are extracted from a Docker container, they belong to root:root - # We need to fix this before the next steps - - name: Fix file permissions - run: sudo chown -R runner:docker . - - # This is needed to run the normalize step - - name: Set up Ruby environment - uses: ./.github/actions/setup-ruby - - - name: Run i18n normalize task - run: bin/i18n-tasks normalize - - # Create or update the pull request - - name: Create Pull Request - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8 - with: - commit-message: 'New Crowdin translations' - title: 'New Crowdin Translations (automated)' - author: 'GitHub Actions ' - body: | - New Crowdin translations, automated with GitHub Actions - - See `.github/workflows/crowdin-download.yml` - - This PR will be updated every day with new translations. - - Due to a limitation in GitHub Actions, checks are not running on this PR without manual action. - If you want to run the checks, then please press “Approve workflows to run”. - branch: i18n/crowdin/translations - base: main - labels: i18n diff --git a/.github/workflows/crowdin-upload.yml b/.github/workflows/crowdin-upload.yml deleted file mode 100644 index 08858de..0000000 --- a/.github/workflows/crowdin-upload.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Crowdin / Upload translations - -on: - push: - branches: - - 'main' - - 'stable-*' - paths: - - crowdin.yml - - app/javascript/mastodon/locales/en.json - - config/locales/en.yml - - config/locales/simple_form.en.yml - - config/locales/activerecord.en.yml - - config/locales/devise.en.yml - - config/locales/doorkeeper.en.yml - - .github/workflows/crowdin-upload.yml - workflow_dispatch: - -jobs: - upload-translations: - runs-on: ubuntu-latest - if: github.repository == 'mastodon/mastodon' - - steps: - - name: Checkout - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - name: crowdin action - uses: crowdin/github-action@c7af9bc98b01694653031fef2a0dc6c7888ce9bc # v2 - with: - upload_sources: true - upload_translations: false - download_translations: false - crowdin_branch_name: ${{ github.base_ref || github.ref_name }} - - env: - CROWDIN_PROJECT_ID: ${{ vars.CROWDIN_PROJECT_ID }} - CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} diff --git a/.github/workflows/format-check.yml b/.github/workflows/format-check.yml deleted file mode 100644 index ee4b262..0000000 --- a/.github/workflows/format-check.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Check formatting -on: - merge_group: - push: - branches: - - 'main' - - 'stable-*' - pull_request: - -jobs: - lint: - runs-on: ubuntu-latest - timeout-minutes: 15 - - steps: - - name: Clone repository - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - name: Set up Javascript environment - uses: ./.github/actions/setup-javascript - - - name: Check formatting - run: yarn format:check diff --git a/.github/workflows/lint-css.yml b/.github/workflows/lint-css.yml deleted file mode 100644 index e69fdc1..0000000 --- a/.github/workflows/lint-css.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: CSS Linting -on: - merge_group: - push: - branches: - - 'main' - - 'stable-*' - paths: - - 'package.json' - - 'yarn.lock' - - '.nvmrc' - - 'stylelint.config.js' - - '**/*.css' - - '**/*.scss' - - '.github/workflows/lint-css.yml' - - pull_request: - paths: - - 'package.json' - - 'yarn.lock' - - '.nvmrc' - - 'stylelint.config.js' - - '**/*.css' - - '**/*.scss' - - '.github/workflows/lint-css.yml' - -jobs: - lint: - runs-on: ubuntu-latest - timeout-minutes: 15 - - steps: - - name: Clone repository - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - name: Set up Javascript environment - uses: ./.github/actions/setup-javascript - - - name: Stylelint - run: yarn lint:css --custom-formatter @csstools/stylelint-formatter-github diff --git a/.github/workflows/lint-haml.yml b/.github/workflows/lint-haml.yml deleted file mode 100644 index fdb6cf1..0000000 --- a/.github/workflows/lint-haml.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Haml Linting -on: - merge_group: - push: - branches: - - 'main' - - 'stable-*' - paths: - - '.github/workflows/lint-haml.yml' - - '.haml-lint*.yml' - - '.rubocop*.yml' - - '.ruby-version' - - '**/*.haml' - - 'Gemfile*' - - pull_request: - paths: - - '.github/workflows/lint-haml.yml' - - '.haml-lint*.yml' - - '.rubocop*.yml' - - '.ruby-version' - - '**/*.haml' - - 'Gemfile*' - -jobs: - lint: - runs-on: ubuntu-latest - timeout-minutes: 15 - - env: - BUNDLE_ONLY: development - - steps: - - name: Clone repository - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - name: Set up Ruby - uses: ruby/setup-ruby@6e5d382445ae5590b7449d8b3bc8cb1c2c27f617 # v1 - with: - bundler-cache: true - - - name: Run haml-lint - run: | - bin/haml-lint --reporter github diff --git a/.github/workflows/lint-js.yml b/.github/workflows/lint-js.yml deleted file mode 100644 index 65c3056..0000000 --- a/.github/workflows/lint-js.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: JavaScript Linting -on: - merge_group: - push: - branches: - - 'main' - - 'stable-*' - paths: - - 'package.json' - - 'yarn.lock' - - 'tsconfig.json' - - '.nvmrc' - - 'eslint.config.mjs' - - '**/*.js' - - '**/*.jsx' - - '**/*.ts' - - '**/*.tsx' - - '.github/workflows/lint-js.yml' - - pull_request: - paths: - - 'package.json' - - 'yarn.lock' - - 'tsconfig.json' - - '.nvmrc' - - 'eslint.config.mjs' - - '**/*.js' - - '**/*.jsx' - - '**/*.ts' - - '**/*.tsx' - - '.github/workflows/lint-js.yml' - -jobs: - lint: - runs-on: ubuntu-latest - timeout-minutes: 15 - - steps: - - name: Clone repository - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - name: Set up Javascript environment - uses: ./.github/actions/setup-javascript - - - name: ESLint - run: yarn workspaces foreach --all --parallel run lint:js --max-warnings 0 - - - name: Typecheck - run: yarn typecheck diff --git a/.github/workflows/lint-ruby.yml b/.github/workflows/lint-ruby.yml deleted file mode 100644 index 950e502..0000000 --- a/.github/workflows/lint-ruby.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Ruby Linting -on: - merge_group: - push: - branches: - - 'main' - - 'stable-*' - paths: - - 'Gemfile*' - - '.rubocop*.yml' - - '.ruby-version' - - 'bin/rubocop' - - '**/*.rb' - - '**/*.rake' - - '.github/workflows/lint-ruby.yml' - - pull_request: - paths: - - 'Gemfile*' - - '.rubocop*.yml' - - '.ruby-version' - - 'bin/rubocop' - - '**/*.rb' - - '**/*.rake' - - '.github/workflows/lint-ruby.yml' - -jobs: - lint: - runs-on: ubuntu-latest - timeout-minutes: 15 - - env: - BUNDLE_ONLY: development - - steps: - - name: Clone repository - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - name: Set up Ruby - uses: ruby/setup-ruby@6e5d382445ae5590b7449d8b3bc8cb1c2c27f617 # v1 - with: - bundler-cache: true - - - name: Run rubocop - run: bin/rubocop --format github - - - name: Run brakeman - if: always() # Run both checks, even if the first failed - run: bin/brakeman diff --git a/.github/workflows/rebase-needed.yml b/.github/workflows/rebase-needed.yml deleted file mode 100644 index cf594c2..0000000 --- a/.github/workflows/rebase-needed.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: PR Needs Rebase - -on: - schedule: - - cron: '0 * * * *' - -permissions: - pull-requests: write - -jobs: - label-rebase-needed: - runs-on: ubuntu-latest - if: github.repository == 'mastodon/mastodon' - - concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - - steps: - - name: Check for merge conflicts - uses: eps1lon/actions-label-merge-conflict@1df065ebe6e3310545d4f4c4e862e43bdca146f0 # v3 - with: - dirtyLabel: 'rebase needed :construction:' - repoToken: '${{ secrets.GITHUB_TOKEN }}' - commentOnClean: This pull request has resolved merge conflicts and is ready for review. - commentOnDirty: This pull request has merge conflicts that must be resolved before it can be merged. - retryMax: 30 - continueOnMissingPermissions: false diff --git a/.github/workflows/test-image-build.yml b/.github/workflows/test-image-build.yml deleted file mode 100644 index 121b8b0..0000000 --- a/.github/workflows/test-image-build.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Test container image build -on: - pull_request: - paths: - - .github/workflows/build-nightly.yml - - .github/workflows/build-push-pr.yml - - .github/workflows/build-releases.yml - - .github/workflows/test-image-build.yml - - Dockerfile - - streaming/Dockerfile - - .dockerignore -permissions: - contents: read - -jobs: - build-image: - concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - - uses: ./.github/workflows/build-container-image.yml - with: - file_to_build: Dockerfile - cache: true - - build-image-streaming: - concurrency: - group: ${{ github.workflow }}-${{ github.ref }}-streaming - cancel-in-progress: true - - uses: ./.github/workflows/build-container-image.yml - with: - file_to_build: streaming/Dockerfile - cache: true diff --git a/.github/workflows/test-js.yml b/.github/workflows/test-js.yml deleted file mode 100644 index 5a3c578..0000000 --- a/.github/workflows/test-js.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: JavaScript Testing -on: - merge_group: - push: - branches: - - 'main' - - 'stable-*' - paths: - - 'package.json' - - 'yarn.lock' - - '.nvmrc' - - '**/*.js' - - '**/*.jsx' - - '**/*.ts' - - '**/*.tsx' - - '**/*.snap' - - '.github/workflows/test-js.yml' - - pull_request: - paths: - - 'package.json' - - 'yarn.lock' - - '.nvmrc' - - '**/*.js' - - '**/*.jsx' - - '**/*.ts' - - '**/*.tsx' - - '**/*.snap' - - '.github/workflows/test-js.yml' - -jobs: - test: - runs-on: ubuntu-latest - timeout-minutes: 15 - - steps: - - name: Clone repository - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - name: Set up Javascript environment - uses: ./.github/actions/setup-javascript - - - name: JavaScript testing - run: yarn test:js diff --git a/.github/workflows/test-migrations.yml b/.github/workflows/test-migrations.yml deleted file mode 100644 index 79268f3..0000000 --- a/.github/workflows/test-migrations.yml +++ /dev/null @@ -1,113 +0,0 @@ -name: Historical data migration test - -on: - merge_group: - push: - branches: - - 'main' - - 'stable-*' - paths: - - 'Gemfile*' - - '.ruby-version' - - '**/*.rb' - - '.github/workflows/test-migrations.yml' - - 'lib/tasks/tests.rake' - - 'lib/tasks/db.rake' - - pull_request: - paths: - - 'Gemfile*' - - '.ruby-version' - - '**/*.rb' - - '.github/workflows/test-migrations.yml' - - 'lib/tasks/tests.rake' - -jobs: - test: - runs-on: ubuntu-latest - timeout-minutes: 15 - - strategy: - fail-fast: false - - matrix: - postgres: - - 14-alpine - - 15-alpine - - 16-alpine - - 17-alpine - - services: - postgres: - image: postgres:${{ matrix.postgres}} - env: - POSTGRES_PASSWORD: postgres - POSTGRES_USER: postgres - options: >- - --health-cmd pg_isready - --health-interval 10ms - --health-timeout 3s - --health-retries 50 - ports: - - 5432:5432 - - redis: - image: redis:7-alpine - options: >- - --health-cmd "redis-cli ping" - --health-interval 10ms - --health-timeout 3s - --health-retries 50 - ports: - - 6379:6379 - - env: - DB_HOST: localhost - DB_USER: postgres - DB_PASS: postgres - RAILS_ENV: test - BUNDLE_CLEAN: true - BUNDLE_FROZEN: true - BUNDLE_WITHOUT: 'development:production' - BUNDLE_JOBS: 3 - BUNDLE_RETRY: 3 - - steps: - - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - name: Set up Ruby environment - uses: ./.github/actions/setup-ruby - - - name: Ensure no errors with `db:prepare` - run: | - bin/rails db:drop - bin/rails db:prepare - bin/rails db:migrate - - - name: Ensure no errors with `db:prepare` and SKIP_POST_DEPLOYMENT_MIGRATIONS - run: | - bin/rails db:drop - SKIP_POST_DEPLOYMENT_MIGRATIONS=true bin/rails db:prepare - bin/rails db:migrate - - - name: Test "one step migration" flow - run: | - bin/rails db:drop - bin/rails db:create - bin/rails tests:migrations:prepare_database - bin/rails db:migrate - bin/rails tests:migrations:check_database - - - name: Test "two step migration" flow - run: | - bin/rails db:drop - bin/rails db:create - SKIP_POST_DEPLOYMENT_MIGRATIONS=true bin/rails tests:migrations:prepare_database - - # Migrate up to v4.3.0 breakpoint - bin/rails db:migrate VERSION=20241007071624 - - # Migrate the rest - SKIP_POST_DEPLOYMENT_MIGRATIONS=true bin/rails db:migrate - bin/rails db:migrate - bin/rails tests:migrations:check_database diff --git a/.github/workflows/test-ruby.yml b/.github/workflows/test-ruby.yml deleted file mode 100644 index 117d6df..0000000 --- a/.github/workflows/test-ruby.yml +++ /dev/null @@ -1,390 +0,0 @@ -name: Ruby Testing - -on: - merge_group: - push: - branches: - - 'main' - - 'stable-*' - pull_request: - -env: - BUNDLE_CLEAN: true - BUNDLE_FROZEN: true - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - build: - name: build (production) - runs-on: ubuntu-latest - timeout-minutes: 15 - - env: - RAILS_ENV: production - BUNDLE_WITH: production - SECRET_KEY_BASE_DUMMY: 1 - - steps: - - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - name: Set up Ruby environment - uses: ./.github/actions/setup-ruby - - - name: Set up Javascript environment - uses: ./.github/actions/setup-javascript - with: - onlyProduction: 'true' - - - name: Cache assets from compilation - uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5 - with: - path: | - public/assets - public/packs - public/packs-test - tmp/cache/vite - key: assets-${{ github.head_ref || github.ref_name }}-${{ github.sha }} - restore-keys: | - assets-${{ github.head_ref || github.ref_name }}-${{ github.sha }} - assets-${{ github.head_ref || github.ref_name }} - assets-main - assets - - - name: Precompile assets - run: |- - bin/rails assets:precompile - - - name: Archive asset artifacts - run: | - tar --exclude={"*.br","*.gz"} -zcf artifacts.tar.gz public/assets public/packs* - - - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - path: |- - ./artifacts.tar.gz - name: ${{ github.sha }} - retention-days: 0 - - test: - runs-on: ubuntu-latest - timeout-minutes: 60 - - needs: - - build - - services: - postgres: - image: postgres:14-alpine - env: - POSTGRES_PASSWORD: postgres - POSTGRES_USER: postgres - options: >- - --health-cmd pg_isready - --health-interval 10ms - --health-timeout 3s - --health-retries 50 - ports: - - 5432:5432 - - redis: - image: redis:7-alpine - options: >- - --health-cmd "redis-cli ping" - --health-interval 10ms - --health-timeout 3s - --health-retries 50 - ports: - - 6379:6379 - - env: - DB_HOST: localhost - DB_USER: postgres - DB_PASS: postgres - COVERAGE: ${{ matrix.ruby-version == '.ruby-version' }} - RAILS_ENV: test - ALLOW_NOPAM: true - PAM_ENABLED: true - PAM_DEFAULT_SERVICE: pam_test - PAM_CONTROLLED_SERVICE: pam_test_controlled - OIDC_ENABLED: true - OIDC_SCOPE: read - SAML_ENABLED: true - CAS_ENABLED: true - BUNDLE_WITH: 'pam_authentication test' - GITHUB_RSPEC: ${{ matrix.ruby-version == '.ruby-version' && github.event.pull_request && 'true' }} - - strategy: - fail-fast: false - matrix: - ruby-version: - - '3.3' - - '3.4' - - '.ruby-version' - steps: - - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 - with: - path: './' - name: ${{ github.sha }} - - - name: Expand archived asset artifacts - run: | - tar xvzf artifacts.tar.gz - - - name: Set up Ruby environment - timeout-minutes: 15 - uses: ./.github/actions/setup-ruby - with: - ruby-version: ${{ matrix.ruby-version}} - additional-system-dependencies: ffmpeg libpam-dev - - - name: Load database schema - run: | - bin/rails db:setup - bin/flatware fan bin/rails db:test:prepare - - - name: Cache RSpec persistence file - uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5 - with: - path: | - tmp/rspec/examples.txt - key: rspec-persistence-${{ github.head_ref || github.ref_name }}-${{ github.sha }} - restore-keys: | - rspec-persistence-${{ github.head_ref || github.ref_name }}-${{ github.sha }}-${{ matrix.ruby-version }} - rspec-persistence-${{ github.head_ref || github.ref_name }}-${{ github.sha }} - rspec-persistence-${{ github.head_ref || github.ref_name }} - rspec-persistence-main - rspec-persistence - - - run: bin/flatware rspec - - - name: Upload coverage reports to Codecov - if: matrix.ruby-version == '.ruby-version' - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v6 - with: - files: coverage/lcov/*.lcov - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - - test-e2e: - name: End to End testing - runs-on: ubuntu-latest - timeout-minutes: 30 - - needs: - - build - - services: - postgres: - image: postgres:14-alpine - env: - POSTGRES_PASSWORD: postgres - POSTGRES_USER: postgres - options: >- - --health-cmd pg_isready - --health-interval 10ms - --health-timeout 3s - --health-retries 50 - ports: - - 5432:5432 - - redis: - image: redis:7-alpine - options: >- - --health-cmd "redis-cli ping" - --health-interval 10ms - --health-timeout 3s - --health-retries 50 - ports: - - 6379:6379 - - env: - DB_HOST: localhost - DB_USER: postgres - DB_PASS: postgres - RAILS_ENV: test - BUNDLE_WITH: test - LOCAL_DOMAIN: localhost:3000 - LOCAL_HTTPS: false - - strategy: - fail-fast: false - matrix: - ruby-version: - - '3.3' - - '3.4' - - '.ruby-version' - - steps: - - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 - with: - path: './' - name: ${{ github.sha }} - - - name: Expand archived asset artifacts - run: | - tar xvzf artifacts.tar.gz - - - name: Set up Ruby environment - uses: ./.github/actions/setup-ruby - timeout-minutes: 15 - with: - ruby-version: ${{ matrix.ruby-version}} - additional-system-dependencies: ffmpeg - - - name: Set up Javascript environment - uses: ./.github/actions/setup-javascript - - - name: Load database schema - run: './bin/rails db:create db:schema:load db:seed' - - - name: Cache Playwright Chromium browser - id: playwright-cache - uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5 - with: - path: ~/.cache/ms-playwright - key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }} - - - name: Install Playwright Chromium browser (with deps) - if: steps.playwright-cache.outputs.cache-hit != 'true' - run: yarn run playwright install --with-deps chromium - - - name: Install Playwright Chromium browser deps - if: steps.playwright-cache.outputs.cache-hit == 'true' - run: yarn run playwright install-deps chromium - - - run: bin/rspec spec/system --tag streaming --tag js - - - name: Archive logs - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - if: failure() - with: - name: e2e-logs-${{ matrix.ruby-version }} - path: log/ - - - name: Archive test screenshots - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - if: failure() - with: - name: e2e-screenshots-${{ matrix.ruby-version }} - path: tmp/capybara/ - - test-search: - name: Elastic Search integration testing - runs-on: ubuntu-latest - timeout-minutes: 30 - - needs: - - build - - services: - postgres: - image: postgres:14-alpine - env: - POSTGRES_PASSWORD: postgres - POSTGRES_USER: postgres - options: >- - --health-cmd pg_isready - --health-interval 10ms - --health-timeout 3s - --health-retries 50 - ports: - - 5432:5432 - - redis: - image: redis:7-alpine - options: >- - --health-cmd "redis-cli ping" - --health-interval 10ms - --health-timeout 3s - --health-retries 50 - ports: - - 6379:6379 - - elasticsearch: - image: ${{ contains(matrix.search-image, 'elasticsearch') && matrix.search-image || '' }} - env: - discovery.type: single-node - xpack.security.enabled: false - options: >- - --health-cmd "curl http://localhost:9200/_cluster/health" - --health-interval 2s - --health-timeout 3s - --health-retries 50 - ports: - - 9200:9200 - - opensearch: - image: ${{ contains(matrix.search-image, 'opensearch') && matrix.search-image || '' }} - env: - discovery.type: single-node - DISABLE_INSTALL_DEMO_CONFIG: true - DISABLE_SECURITY_PLUGIN: true - options: >- - --health-cmd "curl http://localhost:9200/_cluster/health" - --health-interval 2s - --health-timeout 3s - --health-retries 50 - ports: - - 9200:9200 - - env: - DB_HOST: localhost - DB_USER: postgres - DB_PASS: postgres - RAILS_ENV: test - BUNDLE_WITH: test - ES_ENABLED: true - ES_HOST: localhost - ES_PORT: 9200 - - strategy: - fail-fast: false - matrix: - ruby-version: - - '3.3' - - '3.4' - - '.ruby-version' - search-image: - - docker.elastic.co/elasticsearch/elasticsearch:7.17.29 - include: - - ruby-version: '.ruby-version' - search-image: docker.elastic.co/elasticsearch/elasticsearch:8.19.2 - - ruby-version: '.ruby-version' - search-image: opensearchproject/opensearch:2 - - steps: - - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 - with: - path: './' - name: ${{ github.sha }} - - - name: Set up Ruby environment - uses: ./.github/actions/setup-ruby - timeout-minutes: 15 - with: - ruby-version: ${{ matrix.ruby-version}} - additional-system-dependencies: ffmpeg - - - name: Set up Javascript environment - uses: ./.github/actions/setup-javascript - - - name: Load database schema - run: './bin/rails db:create db:schema:load db:seed' - - - run: bin/rspec --tag search - - - name: Archive logs - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - if: failure() - with: - name: test-search-logs-${{ matrix.ruby-version }} - path: log/ diff --git a/COFFEYLABS.md b/COFFEYLABS.md new file mode 100644 index 0000000..80f8747 --- /dev/null +++ b/COFFEYLABS.md @@ -0,0 +1,43 @@ +# Coffey Labs build of Mastodon + +This repository is [Mastodon](https://github.com/mastodon/mastodon) with one +addition: the **coffeylabs** theme, the palette, type and blueprint grid of +coffeylabs.org. It is what runs on linuxexpert.org. Everything else is +upstream Mastodon, unchanged, under the same license (AGPL-3.0, see +[LICENSE](LICENSE)). + +## How it tracks upstream + +Upstream releases come in as snapshots, not as a merged history: the +`upstream` branch holds one unmodified "Import Mastodon vX.Y.Z" commit per +release, and each import is merged into `main` through a pull request. + +## What is changed + +Added (new files, Coffey Labs, 2026-10-06): + +- `app/javascript/styles/coffeylabs.scss` and `app/javascript/styles/coffeylabs/` + -- the theme. It loads the stock stylesheet, then overrides Mastodon's color + tokens and adds the fonts and surfaces. Users can still pick Mastodon's + default theme in their appearance preferences. +- `app/javascript/fonts/coffeylabs/` -- Bricolage Grotesque and JetBrains Mono, + both under the SIL Open Font License (license files alongside). +- `.gitea/workflows/ci.yml` -- builds the image on every change and publishes + it from release tags. +- This file. + +Modified (each carries a notice at the top): + +- `config/themes.yml` -- registers the coffeylabs theme. +- `app/lib/themes.rb` -- the dark browser-bar color matches the theme. +- `Dockerfile` -- `SOURCE_BASE_URL` and `SOURCE_TAG` build arguments, so the + "View source code" link points at this repository. + +Removed: upstream's `.github/workflows`, which run upstream's own CI. + +## Releases + +A tag named `v-coffeylabs.` (e.g. `v4.7.3-coffeylabs.1`) +publishes the `mastodon` image for linux/amd64 to this repository's +packages. The streaming server is unchanged, so use upstream's +`mastodon-streaming` image at the same upstream version. diff --git a/Dockerfile b/Dockerfile index 9e99a52..e36d4c5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,9 @@ # syntax=docker/dockerfile:1.18 +# Modified by Coffey Labs, 2026-10-06: SOURCE_BASE_URL and SOURCE_TAG build +# arguments, so the "View source code" link points at this fork (see +# COFFEYLABS.md). + # This file is designed for production server deployment, not local development work # For a containerized local dev environment, see: https://github.com/mastodon/mastodon/blob/main/docs/DEVELOPMENT.md#docker @@ -32,6 +36,9 @@ ARG MASTODON_VERSION_PRERELEASE="" ARG MASTODON_VERSION_METADATA="" # Will be available as Mastodon::Version.source_commit ARG SOURCE_COMMIT="" +# Where "View source code" points: the fork's repository and its tag +ARG SOURCE_BASE_URL="" +ARG SOURCE_TAG="" # Allow Ruby on Rails to serve static files # See: https://docs.joinmastodon.org/admin/config/#rails_serve_static_files @@ -51,6 +58,8 @@ ENV \ MASTODON_VERSION_PRERELEASE="${MASTODON_VERSION_PRERELEASE}" \ MASTODON_VERSION_METADATA="${MASTODON_VERSION_METADATA}" \ SOURCE_COMMIT="${SOURCE_COMMIT}" \ + SOURCE_BASE_URL="${SOURCE_BASE_URL}" \ + SOURCE_TAG="${SOURCE_TAG}" \ RAILS_SERVE_STATIC_FILES="${RAILS_SERVE_STATIC_FILES}" \ RUBY_YJIT_ENABLE="${RUBY_YJIT_ENABLE}" \ TZ="${TZ}" diff --git a/app/javascript/fonts/coffeylabs/OFL-bricolage.txt b/app/javascript/fonts/coffeylabs/OFL-bricolage.txt new file mode 100644 index 0000000..a397658 --- /dev/null +++ b/app/javascript/fonts/coffeylabs/OFL-bricolage.txt @@ -0,0 +1,93 @@ +Copyright 2022 The Bricolage Grotesque Project Authors (https://github.com/ateliertriay/bricolage) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/app/javascript/fonts/coffeylabs/OFL-jetbrains-mono.txt b/app/javascript/fonts/coffeylabs/OFL-jetbrains-mono.txt new file mode 100644 index 0000000..8f7ed67 --- /dev/null +++ b/app/javascript/fonts/coffeylabs/OFL-jetbrains-mono.txt @@ -0,0 +1,93 @@ +Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono) JetBrainsMono-Italic[wght].ttf: Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/app/javascript/fonts/coffeylabs/bricolage-grotesque-latin-wght-normal.woff2 b/app/javascript/fonts/coffeylabs/bricolage-grotesque-latin-wght-normal.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..82152a40802e0646b7a732744394a02c8c72772f GIT binary patch literal 41344 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