From 0c1a69f574482e5cf7c6293c032551a0b96e528a Mon Sep 17 00:00:00 2001 From: Ant Barnes Date: Thu, 10 Feb 2022 13:09:35 +0000 Subject: [PATCH 1/9] Initial circle setup --- .circle/config.yml | 79 ++++++++++++++++++++++++++++++ .circle/record_coverage | 103 ++++++++++++++++++++++++++++++++++++++++ config/database.yml | 81 +++---------------------------- 3 files changed, 188 insertions(+), 75 deletions(-) create mode 100644 .circle/config.yml create mode 100644 .circle/record_coverage diff --git a/.circle/config.yml b/.circle/config.yml new file mode 100644 index 000000000..4f0bd95ca --- /dev/null +++ b/.circle/config.yml @@ -0,0 +1,79 @@ +jobs: + rubocop: + docker: + - image: 'cimg/ruby:3.0.3' + steps: + - checkout + - ruby/install-deps + - ruby/rubocop-check: + format: progress + label: Inspecting with Rubocop + + test: + docker: + - image: 'cimg/ruby:3.0.3-browsers' + - image: 'circleci/postgres:12.0-alpine-ram' + environment: + POSTGRES_DB: choco_cake_test + POSTGRES_PASSWORD: password + POSTGRES_USER: showcase + - image: 'circleci/redis:6.2-alpine' + + environment: + BUNDLE_JOBS: '3' + BUNDLE_RETRY: '3' + PAGER: '' + POSTGRES_DB: choco_cake_test + POSTGRES_PASSWORD: password + POSTGRES_USER: postgres + POSTGRES_HOST: "127.0.0.1" + RAILS_ENV: test + steps: + - checkout + - browser-tools/install-firefox + - ruby/install-deps + - node/install-packages: + pkg-manager: yarn + - run: + command: 'dockerize -wait tcp://localhost:5432 -timeout 1m' + name: Wait for DB + - run: + command: 'cp .env.example .env' + name: Copy example environment + - run: + command: 'sudo apt-get update && sudo apt-get install --yes --no-install-recommends postgresql-client jq curl imagemagick' + name: Install postgres client, jq, curl, imagemagick + - run: + command: 'bin/rails db:setup --trace' + name: Database setup + - run: + name: Checking factory bot factories + command: bundle exec rake factory_bot:lint + - ruby/rspec-test + - store_artifacts: + path: coverage + - run: + name: Post test coverage to Github + command: bash -ue .circleci/record_coverage + when: always + +orbs: + browser-tools: circleci/browser-tools@1 + node: circleci/node@4 + ruby: circleci/ruby@1.3 + +version: 2.1 + +workflows: + code_quality: + jobs: + - rubocop: + filters: + branches: + ignore: + - master + - main + test: + jobs: + - test: + context: raspberrypigithubbot diff --git a/.circle/record_coverage b/.circle/record_coverage new file mode 100644 index 000000000..9a60a0d4c --- /dev/null +++ b/.circle/record_coverage @@ -0,0 +1,103 @@ +#!/bin/bash -ueo pipefail + +# Record coverage +# +# This script uses the Circle and Github APIs to poke a comment into a PR about test coverage. +# +# To work, the GITHUB_TOKEN and CIRCLE_TOKEN vars must be in the environment, +# with appropriate API tokens from GH and Circle. +# +# Also to get the magic link to your test coverage, you'll want to store the +# `coverage/` directory. +#``` +# - store_artifacts: +# path: coverage +#``` + +CURL_ARGS="-s -S -f" + +function graceful_exit() { + echo "*** Something failed! Exiting gracefully so the build doesn't fail overall" + exit 0 +} + +# +# Wrapper for the Github GraphQL API +# +function gh_query() { + # Build and escape our JSON + json=$(jq -n --arg q "$*" '{query: $q}') + curl $CURL_ARGS -H "Authorization: bearer $GITHUB_TOKEN" -X POST -d "$json" https://api.github.com/graphql +} + + +# Trap any fails, and force a successful exit. +trap graceful_exit ERR + +last_run=coverage/.last_run.json +if ! [ -s $last_run ] ; then + echo "*** No $last_run file found." + exit 0 +fi + +which jq > /dev/null || sudo apt-get install -y jq + +# This is the message that makes it into github +msg="* CircleCI build [#${CIRCLE_BUILD_NUM}](${CIRCLE_BUILD_URL})\n" +msg="$msg* Test coverage: " + + +# Check to see if coverage is under `result.line` or under `result.covered_percent` (older versions) +coverage=$(jq -r 'if .result.line then .result.line else .result.covered_percent end' < coverage/.last_run.json) + +if [ "${coverage}" = "null" ] ; then + echo "*** Failed to determine coverage" + exit 0 +fi + +artifacts_response=$(curl $CURL_ARGS -H "Circle-Token: $CIRCLE_TOKEN" https://circleci.com/api/v1.1/project/gh/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/${CIRCLE_BUILD_NUM}/artifacts) +coverage_url=$(echo ${artifacts_response} | jq -r '. | map(select(.path == "coverage/index.html"))[0].url') + +if ! [ "${coverage_url}" = "null" ] ; then + msg="$msg [$coverage%]($coverage_url)\n\n" +else + msg="$msg $coverage%\n\n" + msg="$msg > CircleCI didn't store the Simplecov index (maybe the store_artifacts step is missing?)" +fi + +# Find associated PR. *NB* we're assuming that the first, open PR is the one +# to comment on. +q="query { + repository(name: \"${CIRCLE_PROJECT_REPONAME}\", owner: \"${CIRCLE_PROJECT_USERNAME}\") { + ref(qualifiedName: \"${CIRCLE_BRANCH}\") { + associatedPullRequests(first: 1) { + nodes { + id + } + } + } + } +}" + +pr_response=$(gh_query $q) +pr_node=$(echo $pr_response | jq -r ".data.repository.ref.associatedPullRequests.nodes[0].id") + +if [ "$pr_node" = "null" ] ; then + echo "*** No PR found" + exit 0 +fi + + +echo ">>> Posting code coverage comment" +m="mutation { + addComment(input: { + subjectId: \"${pr_node}\", + body: \"${msg}\" + }) { + subject { + id + } + } +}" + +gh_query $m diff --git a/config/database.yml b/config/database.yml index 95970000f..9300ccacb 100644 --- a/config/database.yml +++ b/config/database.yml @@ -1,88 +1,19 @@ -# PostgreSQL. Versions 9.3 and up are supported. -# -# Install the pg driver: -# gem install pg -# On macOS with Homebrew: -# gem install pg -- --with-pg-config=/usr/local/bin/pg_config -# On macOS with MacPorts: -# gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config -# On Windows: -# gem install pg -# Choose the win32 build. -# Install PostgreSQL and put its /bin directory on your path. -# -# Configure Using Gemfile -# gem "pg" -# default: &default adapter: postgresql encoding: unicode - # For details on connection pooling, see Rails configuration guide - # https://guides.rubyonrails.org/configuring.html#database-pooling - pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> + host: <%= ENV.fetch('POSTGRES_HOST', 'db') %> + username: <%= ENV.fetch('POSTGRES_USER', 'no_pg_user_set') %> + password: <%= ENV.fetch('POSTGRES_PASSWORD', '') %> + pool: <%= ENV.fetch('RAILS_MAX_THREADS', 5) %> development: <<: *default - host: db - username: postgres - password: password - database: choco_cake_development + database: <%= ENV.fetch('POSTGRES_DB', 'choco_cake_development') %> - # The specified database role being used to connect to postgres. - # To create additional roles in postgres see `$ createuser --help`. - # When left blank, postgres will use the default role. This is - # the same name as the operating system user running Rails. - #username: app - - # The password associated with the postgres role (username). - #password: - - # Connect on a TCP socket. Omitted by default since the client uses a - # domain socket that doesn't need configuration. Windows does not have - # domain sockets, so uncomment these lines. - #host: localhost - - # The TCP port the server listens on. Defaults to 5432. - # If your server runs on a different port number, change accordingly. - #port: 5432 - - # Schema search path. The server defaults to $user,public - #schema_search_path: myapp,sharedapp,public - - # Minimum log levels, in increasing order: - # debug5, debug4, debug3, debug2, debug1, - # log, notice, warning, error, fatal, and panic - # Defaults to warning. - #min_messages: notice - -# Warning: The database defined as "test" will be erased and -# re-generated from your development database when you run "rake". -# Do not set this db to the same as development or production. test: <<: *default - database: choco_cake_test + database: <%= ENV.fetch('POSTGRES_DB', 'choco_cake_test') %> -# As with config/credentials.yml, you never want to store sensitive information, -# like your database password, in your source code. If your source code is -# ever seen by anyone, they now have access to your database. -# -# Instead, provide the password or a full connection URL as an environment -# variable when you boot the app. For example: -# -# DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase" -# -# If the connection URL is provided in the special DATABASE_URL environment -# variable, Rails will automatically merge its configuration values on top of -# the values provided in this file. Alternatively, you can specify a connection -# URL environment variable explicitly: -# -# production: -# url: <%= ENV["MY_APP_DATABASE_URL"] %> -# -# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database -# for a full overview on how database connection configuration can be specified. -# production: <<: *default url: <%= ENV['DATABASE_URL'] %> - From 518e3dd75eb10f52349d8dbba7a0a55411025a19 Mon Sep 17 00:00:00 2001 From: Ant Barnes Date: Thu, 10 Feb 2022 13:13:54 +0000 Subject: [PATCH 2/9] Rename folder --- {.circle => .circleci}/config.yml | 0 {.circle => .circleci}/record_coverage | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {.circle => .circleci}/config.yml (100%) rename {.circle => .circleci}/record_coverage (100%) diff --git a/.circle/config.yml b/.circleci/config.yml similarity index 100% rename from .circle/config.yml rename to .circleci/config.yml diff --git a/.circle/record_coverage b/.circleci/record_coverage similarity index 100% rename from .circle/record_coverage rename to .circleci/record_coverage From 9c360a612564261d77640b8e23d2755f5acbb99f Mon Sep 17 00:00:00 2001 From: Ant Barnes Date: Thu, 10 Feb 2022 13:18:58 +0000 Subject: [PATCH 3/9] Tweak config --- .circleci/config.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4f0bd95ca..94b85b061 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -32,23 +32,15 @@ jobs: - checkout - browser-tools/install-firefox - ruby/install-deps - - node/install-packages: - pkg-manager: yarn - run: command: 'dockerize -wait tcp://localhost:5432 -timeout 1m' name: Wait for DB - - run: - command: 'cp .env.example .env' - name: Copy example environment - run: command: 'sudo apt-get update && sudo apt-get install --yes --no-install-recommends postgresql-client jq curl imagemagick' name: Install postgres client, jq, curl, imagemagick - run: command: 'bin/rails db:setup --trace' name: Database setup - - run: - name: Checking factory bot factories - command: bundle exec rake factory_bot:lint - ruby/rspec-test - store_artifacts: path: coverage From 13deea9797f0b22cee1a5fec099a43ee79e919bd Mon Sep 17 00:00:00 2001 From: Ant Barnes Date: Thu, 10 Feb 2022 13:21:54 +0000 Subject: [PATCH 4/9] Amend postgres user --- .circleci/config.yml | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 94b85b061..bfc9eb88f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,13 +1,14 @@ jobs: - rubocop: - docker: - - image: 'cimg/ruby:3.0.3' - steps: - - checkout - - ruby/install-deps - - ruby/rubocop-check: - format: progress - label: Inspecting with Rubocop + # Project has lots of rubocop fixing to do. Enable this once fixed in separate pr. + # rubocop: + # docker: + # - image: 'cimg/ruby:3.0.3' + # steps: + # - checkout + # - ruby/install-deps + # - ruby/rubocop-check: + # format: progress + # label: Inspecting with Rubocop test: docker: @@ -16,7 +17,7 @@ jobs: environment: POSTGRES_DB: choco_cake_test POSTGRES_PASSWORD: password - POSTGRES_USER: showcase + POSTGRES_USER: choco - image: 'circleci/redis:6.2-alpine' environment: @@ -25,7 +26,7 @@ jobs: PAGER: '' POSTGRES_DB: choco_cake_test POSTGRES_PASSWORD: password - POSTGRES_USER: postgres + POSTGRES_USER: choco POSTGRES_HOST: "127.0.0.1" RAILS_ENV: test steps: From da175955f21da711d4eb1dc7943527e154f7a43c Mon Sep 17 00:00:00 2001 From: Ant Barnes Date: Thu, 10 Feb 2022 13:22:29 +0000 Subject: [PATCH 5/9] Properly disable rubocop job --- .circleci/config.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index bfc9eb88f..fddfa822c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -58,14 +58,14 @@ orbs: version: 2.1 workflows: - code_quality: - jobs: - - rubocop: - filters: - branches: - ignore: - - master - - main + # code_quality: + # jobs: + # - rubocop: + # filters: + # branches: + # ignore: + # - master + # - main test: jobs: - test: From 534e85c02d2b7be5b1fe06557989b98db29d8a56 Mon Sep 17 00:00:00 2001 From: Ant Barnes Date: Thu, 10 Feb 2022 13:26:11 +0000 Subject: [PATCH 6/9] Add rspec junit formatter --- Gemfile | 2 ++ Gemfile.lock | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/Gemfile b/Gemfile index 9e00b3024..3cadaaae8 100644 --- a/Gemfile +++ b/Gemfile @@ -18,6 +18,8 @@ group :development, :test do gem 'dotenv-rails' gem 'factory_bot_rails' gem 'faker' + gem 'rspec' + gem 'rspec_junit_formatter' gem 'rspec-rails' gem 'rubocop' end diff --git a/Gemfile.lock b/Gemfile.lock index 015db9226..13e297865 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -147,6 +147,10 @@ GEM rake (13.0.6) regexp_parser (2.2.0) rexml (3.2.5) + rspec (3.10.0) + rspec-core (~> 3.10.0) + rspec-expectations (~> 3.10.0) + rspec-mocks (~> 3.10.0) rspec-core (3.10.1) rspec-support (~> 3.10.0) rspec-expectations (3.10.1) @@ -164,6 +168,8 @@ GEM rspec-mocks (~> 3.10) rspec-support (~> 3.10) rspec-support (3.10.3) + rspec_junit_formatter (0.5.1) + rspec-core (>= 2, < 4, != 2.12.0) rubocop (1.23.0) parallel (~> 1.10) parser (>= 3.0.0.0) @@ -214,7 +220,9 @@ DEPENDENCIES puma (~> 5.0) rack-cors rails (~> 7.0.0) + rspec rspec-rails + rspec_junit_formatter rubocop shoulda-matchers (~> 5.0) sprockets-rails From c1d745d1c7a27f78736d1dd6f151df2e38551510 Mon Sep 17 00:00:00 2001 From: Ant Barnes Date: Thu, 10 Feb 2022 14:07:26 +0000 Subject: [PATCH 7/9] Update specs --- .circleci/config.yml | 2 +- Gemfile.lock | 3 +++ spec/models/project_spec.rb | 11 ++++++++--- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index fddfa822c..82e49ead9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -31,7 +31,7 @@ jobs: RAILS_ENV: test steps: - checkout - - browser-tools/install-firefox + # - browser-tools/install-firefox - ruby/install-deps - run: command: 'dockerize -wait tcp://localhost:5432 -timeout 1m' diff --git a/Gemfile.lock b/Gemfile.lock index 13e297865..5d9f44789 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -103,6 +103,8 @@ GEM nokogiri (1.12.5) mini_portile2 (~> 2.6.1) racc (~> 1.4) + nokogiri (1.12.5-x86_64-darwin) + racc (~> 1.4) nokogiri (1.12.5-x86_64-linux) racc (~> 1.4) parallel (1.21.0) @@ -207,6 +209,7 @@ GEM PLATFORMS aarch64-linux + x86_64-darwin-20 x86_64-linux DEPENDENCIES diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 72785e11e..07f11b8f2 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -8,15 +8,20 @@ end describe 'identifier not nil' do - subject { FactoryBot.build(:project) } - it { is_expected.not_to allow_value(nil).for(:identifier) } + it 'generates an identifier if not present' do + proj = FactoryBot.build(:project, identifier: nil) + expect { proj.valid? } + .to change { proj.identifier.nil? } + .from(true) + .to(false) + end end describe 'identifier unique' do it do project1 = FactoryBot.create(:project) project2 = FactoryBot.build(:project, identifier: project1.identifier) - expect { project2.valid? }.to change { project2.identifier } + expect { project2.valid? }.to change(project2, :identifier) end end end From b6b78a8397745a23c468a8909b9511a173f9fda2 Mon Sep 17 00:00:00 2001 From: Ant Barnes Date: Thu, 10 Feb 2022 14:17:05 +0000 Subject: [PATCH 8/9] Add simplecov --- Gemfile | 1 + Gemfile.lock | 8 ++++++++ spec/rails_helper.rb | 5 +++++ 3 files changed, 14 insertions(+) diff --git a/Gemfile b/Gemfile index 3cadaaae8..d7b391af2 100644 --- a/Gemfile +++ b/Gemfile @@ -22,6 +22,7 @@ group :development, :test do gem 'rspec_junit_formatter' gem 'rspec-rails' gem 'rubocop' + gem 'simplecov', require: false end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index 5d9f44789..ca7e1b59c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -67,6 +67,7 @@ GEM concurrent-ruby (1.1.9) crass (1.0.6) diff-lcs (1.4.4) + docile (1.4.0) dotenv (2.7.6) dotenv-rails (2.7.6) dotenv (= 2.7.6) @@ -186,6 +187,12 @@ GEM ruby-progressbar (1.11.0) shoulda-matchers (5.0.0) activesupport (>= 5.2.0) + simplecov (0.21.2) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.12.3) + simplecov_json_formatter (0.1.3) sprockets (4.0.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) @@ -228,6 +235,7 @@ DEPENDENCIES rspec_junit_formatter rubocop shoulda-matchers (~> 5.0) + simplecov sprockets-rails stimulus-rails turbo-rails diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index b4c930509..54505930c 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -1,4 +1,9 @@ # This file is copied to spec/ when you run 'rails generate rspec:install' +require 'simplecov' +SimpleCov.start 'rails' do + enable_coverage :branch +end + require 'spec_helper' ENV['RAILS_ENV'] ||= 'test' require File.expand_path('../config/environment', __dir__) From 4d9e91eee9983125fdea69752e547ea1d2a7dc3a Mon Sep 17 00:00:00 2001 From: Ant Barnes Date: Thu, 10 Feb 2022 14:20:35 +0000 Subject: [PATCH 9/9] Add new vars to .env.example --- .env.example | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.env.example b/.env.example index a4c5cba9a..f11568174 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,4 @@ ALLOWED_ORIGINS=localhost:3002,localhost:3000 +POSTGRES_HOST=changeme +POSTGRES_USER=changeme +POSTGRES_PASSWORD=changeme