diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..68390ec8 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,83 @@ +version: 2.1 + +workflows: + version: 2 + build: + jobs: + - build_and_test +jobs: + build_and_test: + working_directory: ~/pinafore + docker: + # see https://discuss.circleci.com/t/build-failed-the-engine-node-is-incompatible-with-this-module-expected-version-12-x-got-14-15-0/37921/7 + - image: circleci/ruby@sha256:b018ec2a8f0bbf06880735d2801402bad316c465edb60663be83ac8f1086b805 + - image: circleci/postgres:12.2 + environment: + POSTGRES_USER: pinafore + POSTGRES_PASSWORD: pinafore + POSTGRES_DB: pinafore_development + BROWSER: chrome:headless + - image: circleci/redis:5-alpine + steps: + - checkout + - run: + name: Install system dependencies + command: | + sudo apt-get update + sudo apt-get install -y ffmpeg fonts-noto-color-emoji libicu-dev libidn11-dev libprotobuf-dev postgresql-contrib protobuf-compiler + - run: + name: Check node version + command: node -v + - restore_cache: + name: Restore yarn cache + key: dependency-cache-{{ checksum "yarn.lock" }} + - run: + name: Yarn install + command: yarn install --immutable + - run: + name: Clone mastodon + command: yarn clone-mastodon + - restore_cache: + name: Restore bundler cache + key: bundler-{{ checksum "mastodon/Gemfile.lock" }} + - run: + name: Lint + command: yarn lint + - run: + name: Unit tests + command: yarn test-unit + - run: + name: Wait for postgres to be ready + command: | + for i in `seq 1 10`; + do + nc -z localhost 5432 && echo Success && exit 0 + echo -n . + sleep 1 + done + echo Failed waiting for postgres && exit 1 + - run: + name: Wait for redis to be ready + command: | + for i in `seq 1 10`; + do + nc -z localhost 6379 && echo Success && exit 0 + echo -n . + sleep 1 + done + echo Failed waiting for redis && exit 1 + - run: + name: Integration tests + command: | + node -v + yarn test + - save_cache: + name: Save yarn cache + key: dependency-cache-{{ checksum "yarn.lock" }} + paths: + - ~/.cache/yarn + - save_cache: + name: Save bundler cache + key: bundler-{{ checksum "mastodon/Gemfile.lock" }} + paths: + - mastodon/vendor/bundle diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f2209eb0..00000000 --- a/.travis.yml +++ /dev/null @@ -1,74 +0,0 @@ -language: node_js -node_js: -- '10' -dist: bionic -group: dev -sudo: false -services: -- redis-server -- postgresql -addons: - chrome: stable - postgresql: '10' - apt: - packages: - - autoconf - - bison - - build-essential - - ffmpeg - - file - - g++ - - gcc - - imagemagick - - libffi-dev - - libgdbm5 - - libicu-dev - - libidn11-dev - - libncurses5-dev - - libpq-dev - - libprotobuf-dev - - libreadline6-dev - - libssl-dev - - libxml2-dev - - libxslt1-dev - - libyaml-dev - - pkg-config - - postgresql-client-10 - - postgresql-contrib-10 - - protobuf-compiler - - redis-server - - redis-tools - - zlib1g-dev - - fonts-noto-color-emoji -before_install: -- psql -d template1 -U postgres -c "CREATE USER pinafore WITH PASSWORD 'pinafore' - CREATEDB;" -- curl -o- -L https://yarnpkg.com/install.sh | bash -s -- export PATH="$HOME/.yarn/bin:$PATH" -- "./bin/setup-mastodon-in-travis.sh" -before_script: -- yarn run lint -after_script: -- rm -f /home/travis/.rvm/gems/ruby-*/bin/posix-spawn-benchmark -script: travis_retry yarn run $COMMAND -env: - global: - - ESM_DISABLE_CACHE=1 - - TERSER_DISABLE_CACHE=1 - - secure: kLsuDI1c2/g72Ek2dQZCxpKiEwkSNzB73zddeHyQ/BPNis0FKz172ul28Oeq1eb+tfg51nWq43NBCQ5PtHAjF+O7DbHR1+shj0dyQgMk86aZDVQTp4o5dX3hWyM04apc9hVUVqrCsCP3bHztcdyBu6Lb2QC2dlz8tfYxytcd0T1sQYd08Z5F3jf3rCASccAZ1XS+w3a3yQoD/uu9nsQCIgGpDRGNAt6mPGw4zk8ZmpswA6XPTsfaNZFhln72yQWVCOl+7WD8S2qiBGEXONaVz4/LB/1uo9+i2iPIMhOON91oi0SSacxfYAVsV0wh4L2IEhkbLBvPYI4lelV39U0asTEHBcQmay73KQr8K4aYK7NnK7NK56W/vlJXd6c2Qd0NtUmY5yTGPBJQHtGCDSXIHijXHlmA+NGwJfoDUL7QDNAoC0StR8uSPnAQ4NdfheBSf6l7kKOo5HZwjK4JTWfTvr549TMJnFr9fYNJii9W/MyajLed0wF5nPJ50VyIXX9BAMa7n8KSQ1YV0W9Kp88LHAfASUGjo2P5IddgC3CaM/WAoMWOW5D3vWCWhIQzSmJLz66vUqi3oaiglw+/Q77nrDDE+2zkQGCl6Ehof27TFJRMu2QnT6El3upsRfnMgV3MdO3Kd2Pq0iFSXqPZQIAyba1LAQcveh/OPWmKWjzGkew= -matrix: - include: - - env: BROWSER=chrome:headless COMMAND=test-browser-suite0 - - env: BROWSER=chrome:headless COMMAND=test-browser-suite1 - - env: COMMAND=test-unit - - env: COMMAND=deploy-all-travis - allow_failures: - - env: COMMAND=deploy-all-travis -branches: - only: - - master -cache: - yarn: true - bundler: true - directories: - - "/home/travis/.rvm/" diff --git a/README.md b/README.md index 54e68436..7c641982 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Pinafore [![Build Status](https://travis-ci.com/nolanlawson/pinafore.svg?branch=master)](https://travis-ci.com/nolanlawson/pinafore) +# Pinafore [![Build status](https://circleci.com/gh/nolanlawson/pinafore.svg?style=svg)](https://app.circleci.com/pipelines/gh/nolanlawson/pinafore) An alternative web client for [Mastodon](https://joinmastodon.org), focused on speed and simplicity. @@ -91,10 +91,10 @@ To keep your version of Pinafore up to date, you can use `git` to check out the ### Exporting -Pinafore is a static site. When you run `yarn build`, static files will be +Pinafore is a static site. When you run `yarn build`, static files will be written to `__sapper__/export`. -In theory you could host these static files yourself (e.g. using nginx or Apache), but +In theory you could host these static files yourself (e.g. using nginx or Apache), but it's not recommended, because: - You'd have to set the [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) headers yourself, @@ -103,7 +103,7 @@ which are an important security feature. ## Developing and testing -See [CONTRIBUTING.md](https://github.com/nolanlawson/pinafore/blob/master/CONTRIBUTING.md) for +See [CONTRIBUTING.md](https://github.com/nolanlawson/pinafore/blob/master/CONTRIBUTING.md) for how to run Pinafore in dev mode and run tests. ## Changelog diff --git a/bin/clone-mastodon.js b/bin/clone-mastodon.js new file mode 100644 index 00000000..ad400951 --- /dev/null +++ b/bin/clone-mastodon.js @@ -0,0 +1,35 @@ +import { promisify } from 'util' +import childProcessPromise from 'child-process-promise' +import path from 'path' +import fs from 'fs' +import { envFile } from './mastodon-config' + +const exec = childProcessPromise.exec +const stat = promisify(fs.stat) +const writeFile = promisify(fs.writeFile) +const dir = __dirname + +const GIT_URL = 'https://github.com/tootsuite/mastodon.git' +const GIT_TAG_OR_COMMIT = 'v3.1.3' +const GIT_BRANCH = 'master' + +const mastodonDir = path.join(dir, '../mastodon') + +export default async function cloneMastodon () { + try { + await stat(mastodonDir) + } catch (e) { + console.log('Cloning mastodon...') + await exec(`git clone --single-branch --branch ${GIT_BRANCH} ${GIT_URL} "${mastodonDir}"`) + await exec('git fetch origin --tags', { cwd: mastodonDir }) // may already be cloned, e.g. in CI + await exec(`git checkout ${GIT_TAG_OR_COMMIT}`, { cwd: mastodonDir }) + await writeFile(path.join(dir, '../mastodon/.env'), envFile, 'utf8') + } +} + +if (require.main === module) { + cloneMastodon().catch(err => { + console.error(err) + process.exit(1) + }) +} diff --git a/bin/deploy-all-travis.sh b/bin/deploy-all-travis.sh deleted file mode 100755 index ef76cc34..00000000 --- a/bin/deploy-all-travis.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -set -e -set -x - -if [ "$TRAVIS_BRANCH" = master -a "$TRAVIS_PULL_REQUEST" = false ]; then - yarn run deploy-dev -fi diff --git a/bin/mastodon-config.js b/bin/mastodon-config.js new file mode 100644 index 00000000..44c98f68 --- /dev/null +++ b/bin/mastodon-config.js @@ -0,0 +1,16 @@ +export const DB_NAME = 'pinafore_development' +export const DB_USER = 'pinafore' +export const DB_PASS = 'pinafore' +export const DB_PORT = process.env.PGPORT || 5432 +export const DB_HOST = '127.0.0.1' + +export const envFile = ` +PAPERCLIP_SECRET=foo +SECRET_KEY_BASE=bar +OTP_SECRET=foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar +DB_HOST=${DB_HOST} +DB_PORT=${DB_PORT} +DB_USER=${DB_USER} +DB_NAME=${DB_NAME} +DB_PASS=${DB_PASS} +` diff --git a/bin/run-mastodon.js b/bin/run-mastodon.js index 7945a47c..7805a2f4 100644 --- a/bin/run-mastodon.js +++ b/bin/run-mastodon.js @@ -5,50 +5,18 @@ import path from 'path' import fs from 'fs' import { waitForMastodonUiToStart, waitForMastodonApiToStart } from './wait-for-mastodon-to-start' import mkdirp from 'mkdirp' +import cloneMastodon from './clone-mastodon' +import { DB_USER, DB_PASS, DB_NAME, DB_HOST, DB_PORT } from './mastodon-config' const exec = childProcessPromise.exec const spawn = childProcessPromise.spawn const stat = promisify(fs.stat) const writeFile = promisify(fs.writeFile) const dir = __dirname - -const GIT_URL = 'https://github.com/tootsuite/mastodon.git' -const GIT_TAG_OR_COMMIT = 'v3.1.3' -const GIT_BRANCH = 'master' - -const DB_NAME = 'pinafore_development' -const DB_USER = 'pinafore' -const DB_PASS = 'pinafore' -const DB_PORT = process.env.PGPORT || 5432 -const DB_HOST = '127.0.0.1' - -const envFile = ` -PAPERCLIP_SECRET=foo -SECRET_KEY_BASE=bar -OTP_SECRET=foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar -DB_HOST=${DB_HOST} -DB_PORT=${DB_PORT} -DB_USER=${DB_USER} -DB_NAME=${DB_NAME} -DB_PASS=${DB_PASS} -` - const mastodonDir = path.join(dir, '../mastodon') let childProc -async function cloneMastodon () { - try { - await stat(mastodonDir) - } catch (e) { - console.log('Cloning mastodon...') - await exec(`git clone --single-branch --branch ${GIT_BRANCH} ${GIT_URL} "${mastodonDir}"`) - await exec('git fetch origin --tags', { cwd: mastodonDir }) // may already be cloned, e.g. in CI - await exec(`git checkout ${GIT_TAG_OR_COMMIT}`, { cwd: mastodonDir }) - await writeFile(path.join(dir, '../mastodon/.env'), envFile, 'utf8') - } -} - async function setupMastodonDatabase () { console.log('Setting up mastodon database...') try { @@ -109,8 +77,8 @@ async function runMastodon () { await writeFile(installedFile, '', 'utf8') } const promise = spawn('foreman', ['start'], { cwd, env }) - // don't bother writing to mastodon.log in Travis; we can't read the file anyway - const logFile = process.env.TRAVIS === 'true' ? '/dev/null' : 'mastodon.log' + // don't bother writing to mastodon.log in CI; we can't read the file anyway + const logFile = process.env.CIRCLECI ? '/dev/null' : 'mastodon.log' const log = fs.createWriteStream(logFile, { flags: 'a' }) childProc = promise.childProcess childProc.stdout.pipe(log) diff --git a/bin/setup-mastodon-in-travis.sh b/bin/setup-mastodon-in-travis.sh deleted file mode 100755 index c453516f..00000000 --- a/bin/setup-mastodon-in-travis.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash - -set -e - -if [[ "$COMMAND" = deploy-all-travis || "$COMMAND" = test-unit ]]; then - exit 0 # no need to setup mastodon in this case -fi - -# install ruby -source "$HOME/.rvm/scripts/rvm" -rvm install 2.6.6 -rvm use 2.6.6 - -# check versions -ruby --version -node --version -yarn --version -postgres --version -redis-server --version -ffmpeg -version diff --git a/package.json b/package.json index bacf6efd..91348ed2 100644 --- a/package.json +++ b/package.json @@ -17,14 +17,11 @@ "build-template-html": "node -r esm ./bin/build-template-html.js", "build-template-html-watch": "node -r esm ./bin/build-template-html.js --watch", "build-assets": "node -r esm ./bin/build-assets.js", + "clone-mastodon": "node -r esm ./bin/clone-mastodon.js", "run-mastodon": "node -r esm ./bin/run-mastodon.js", "test": "cross-env BROWSER=chrome:headless run-s test-browser", "test-browser": "run-p --race run-mastodon build-and-start test-mastodon", "test-mastodon": "run-s wait-for-mastodon-to-start wait-for-mastodon-data testcafe", - "test-browser-suite0": "run-p --race run-mastodon build-and-start test-mastodon-suite0", - "test-mastodon-suite0": "run-s wait-for-mastodon-to-start wait-for-mastodon-data testcafe-suite0", - "test-browser-suite1": "run-p --race run-mastodon build-and-start test-mastodon-suite1", - "test-mastodon-suite1": "run-s wait-for-mastodon-to-start wait-for-mastodon-data testcafe-suite1", "testcafe": "run-s testcafe-suite0 testcafe-suite1", "testcafe-suite0": "cross-env-shell testcafe -c 4 $BROWSER tests/spec/0*", "testcafe-suite1": "cross-env-shell testcafe $BROWSER tests/spec/1*", @@ -33,7 +30,6 @@ "wait-for-mastodon-data": "node -r esm bin/wait-for-mastodon-data.js", "deploy-prod": "DEPLOY_TYPE=prod ./bin/deploy.sh", "deploy-dev": "DEPLOY_TYPE=dev ./bin/deploy.sh", - "deploy-all-travis": "./bin/deploy-all-travis.sh", "backup-mastodon-data": "./bin/backup-mastodon-data.sh", "sapper-export": "cross-env PORT=22939 sapper export", "print-export-info": "node ./bin/print-export-info.js",