Skip to content

Commit bdf6806

Browse files
authored
Technical/Update CI/CD flow (#58)
* Added new bunch of project linters * Added auto deploy to RubyGems * Added auto creating release notes on GitHub * Added lefthook config, removed overcommit * Updated gemspecs * Updated codeclimate/circleci configs * Updated gem development dependencies * Updated gem version, changelog
1 parent a9b27f6 commit bdf6806

22 files changed

Lines changed: 281 additions & 119 deletions

.circleci/config.yml

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
---
2+
13
version: 2.1
24

35
defaults: &defaults
@@ -13,26 +15,42 @@ references:
1315
restore_cache:
1416
keys:
1517
- ruby-smtp-mock-{{ checksum "smtp_mock.gemspec" }}
18+
paths:
19+
- ~/vendor/bundle
1620

1721
bundle_install: &bundle_install
1822
run:
1923
name: Installing gems
2024
command: |
21-
bundle config set --local path 'vendor/bundle'
25+
bundle config set --local path '~/vendor/bundle'
2226
bundle install
2327
2428
save_bundle_cache: &save_bundle_cache
2529
save_cache:
2630
key: ruby-smtp-mock-{{ checksum "smtp_mock.gemspec" }}
2731
paths:
28-
- vendor/bundle
32+
- ~/vendor/bundle
2933

3034
system_dependencies: &system_dependencies
3135
run:
3236
name: Installing system requirements
3337
command: |
3438
bundle exec smtp_mock -s -i ~
3539
40+
install_yamllint: &install_yamllint
41+
run:
42+
name: Installing Yamllint
43+
command: |
44+
sudo apt-get update -y
45+
sudo apt-get install -y yamllint
46+
47+
install_lefthook: &install_lefthook
48+
run:
49+
name: Installing Lefthook
50+
command: |
51+
curl -1sLf 'https://dl.cloudsmith.io/public/evilmartians/lefthook/setup.deb.sh' | sudo -E bash
52+
sudo apt-get install -y lefthook
53+
3654
install_codeclimate_reporter: &install_codeclimate_reporter
3755
run:
3856
name: Installing CodeClimate test reporter
@@ -43,14 +61,12 @@ references:
4361
use_latest_gemspec: &use_latest_gemspec
4462
run:
4563
name: Using latest gemspec
46-
command: |
47-
cp .circleci/gemspec_latest smtp_mock.gemspec
64+
command: cp .circleci/gemspecs/latest smtp_mock.gemspec
4865

4966
use_compatible_gemspec: &use_compatible_gemspec
5067
run:
5168
name: Using compatible gemspec
52-
command: |
53-
cp .circleci/gemspec_compatible smtp_mock.gemspec
69+
command: cp .circleci/gemspecs/compatible smtp_mock.gemspec
5470

5571
jobs:
5672
linters-ruby:
@@ -67,12 +83,23 @@ jobs:
6783
- <<: *restore_bundle_cache
6884
- <<: *bundle_install
6985
- <<: *save_bundle_cache
86+
- <<: *install_yamllint
87+
- <<: *install_lefthook
88+
89+
- run:
90+
name: Running code style linters
91+
command: lefthook run code-style-linters
7092

7193
- run:
72-
name: Running Overcommit
94+
name: Running code performance linters
7395
command: |
74-
bundle exec overcommit -s
75-
SKIP=AuthorEmail,AuthorName bundle exec overcommit -r
96+
cp .circleci/linter_configs/.fasterer.yml .fasterer.yml
97+
lefthook run code-performance-linters
98+
rm .fasterer.yml
99+
100+
- run:
101+
name: Running code vulnerability linters
102+
command: lefthook run code-vulnerability-linters
76103

77104
tests-ruby:
78105
parameters:
@@ -116,22 +143,45 @@ jobs:
116143
parameters:
117144
ruby-version:
118145
type: string
119-
docker:
120-
- image: cimg/ruby:<< parameters.ruby-version >>
146+
147+
<<: *defaults
148+
121149
steps:
122150
- checkout
151+
123152
- <<: *use_compatible_gemspec
153+
124154
- ruby/install-deps:
125155
bundler-version: "2.3.26"
126156
with-cache: false
127-
path: './vendor/custom_bundle'
157+
path: '~/vendor/custom_bundle'
158+
128159
- <<: *system_dependencies
160+
129161
- run:
130162
name: Running compatibility tests
131163
command: bundle exec rspec
132164

165+
releasing-gem-from-ruby:
166+
parameters:
167+
ruby-version:
168+
type: string
169+
170+
<<: *defaults
171+
172+
steps:
173+
- checkout
174+
175+
- add_ssh_keys:
176+
fingerprints:
177+
- "55:d3:88:af:10:c9:b1:9d:53:f4:d8:fc:79:4c:69:f7"
178+
179+
- run:
180+
name: Publishing new release
181+
command: ./.circleci/scripts/release.sh
182+
133183
workflows:
134-
build_and_test:
184+
build_test_deploy:
135185
jobs:
136186
- linters-ruby:
137187
matrix:
@@ -145,3 +195,14 @@ workflows:
145195
matrix:
146196
parameters:
147197
ruby-version: ["2.5", "2.6", "2.7", "3.0"]
198+
- releasing-gem-from-ruby:
199+
requires:
200+
- linters-ruby
201+
- tests-ruby
202+
- compatibility-ruby
203+
matrix:
204+
parameters:
205+
ruby-version: ["2.5"]
206+
filters:
207+
branches:
208+
only: master

.circleci/gemspec_compatible

Lines changed: 0 additions & 37 deletions
This file was deleted.

.circleci/gemspecs/compatible

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# frozen_string_literal: true
2+
3+
require_relative 'lib/smtp_mock/version'
4+
5+
Gem::Specification.new do |spec|
6+
spec.name = 'smtp_mock'
7+
spec.version = SmtpMock::VERSION
8+
spec.authors = ['Vladislav Trotsenko']
9+
spec.email = %w[admin@bestweb.com.ua]
10+
spec.summary = %(smtp_mock)
11+
spec.description = %(💎 Ruby SMTP mock. Mimic any SMTP server behaviour for your test environment.)
12+
spec.homepage = 'https://github.com/mocktools/ruby-smtp-mock'
13+
spec.license = 'MIT'
14+
15+
dry_struct_version = ::Gem::Version.new(::RUBY_VERSION) >= ::Gem::Version.new('2.7.0') ? '~> 1.6' : '~> 1.4'
16+
17+
spec.required_ruby_version = '>= 2.5.0'
18+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19+
spec.executables = %w[smtp_mock]
20+
spec.require_paths = %w[lib]
21+
22+
spec.add_runtime_dependency 'dry-struct', dry_struct_version
23+
24+
spec.add_development_dependency 'ffaker'
25+
spec.add_development_dependency 'rake'
26+
spec.add_development_dependency 'rspec'
27+
end
Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,24 @@ Gem::Specification.new do |spec|
66
spec.name = 'smtp_mock'
77
spec.version = SmtpMock::VERSION
88
spec.authors = ['Vladislav Trotsenko']
9-
spec.email = ['admin@bestweb.com.ua']
10-
9+
spec.email = %w[admin@bestweb.com.ua]
1110
spec.summary = %(smtp_mock)
1211
spec.description = %(💎 Ruby SMTP mock. Mimic any SMTP server behaviour for your test environment.)
13-
1412
spec.homepage = 'https://github.com/mocktools/ruby-smtp-mock'
1513
spec.license = 'MIT'
1614

17-
spec.metadata = {
18-
'homepage_uri' => 'https://github.com/mocktools/ruby-smtp-mock',
19-
'changelog_uri' => 'https://github.com/mocktools/ruby-smtp-mock/blob/master/CHANGELOG.md',
20-
'source_code_uri' => 'https://github.com/mocktools/ruby-smtp-mock',
21-
'documentation_uri' => 'https://github.com/mocktools/ruby-smtp-mock/blob/master/README.md',
22-
'bug_tracker_uri' => 'https://github.com/mocktools/ruby-smtp-mock/issues'
23-
}
24-
2515
spec.required_ruby_version = '>= 2.5.0'
26-
27-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
28-
spec.executables = %w[smtp_mock]
16+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17+
spec.executables = %w[smtp_mock]
2918
spec.require_paths = %w[lib]
30-
spec.post_install_message = 'smtpmock is required system dependency. For more details run: `bundle exec smtp_mock -h`'
3119

3220
spec.add_runtime_dependency 'dry-struct', '~> 1.6'
3321

3422
spec.add_development_dependency 'bundler-audit', '~> 0.9.1'
3523
spec.add_development_dependency 'fasterer', '~> 0.10.0'
3624
spec.add_development_dependency 'ffaker', '~> 2.21'
25+
spec.add_development_dependency 'mdl', '~> 0.12.0'
3726
spec.add_development_dependency 'net-smtp', '~> 0.3.3'
38-
spec.add_development_dependency 'overcommit', '~> 0.59.1'
3927
spec.add_development_dependency 'pry-byebug', '~> 3.10', '>= 3.10.1'
4028
spec.add_development_dependency 'rake', '~> 13.0', '>= 13.0.6'
4129
spec.add_development_dependency 'reek', '~> 6.1', '>= 6.1.1'
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
3+
ignore:
4+
- EXA-MPLE-XXXX
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
3+
exclude_paths:
4+
- '.circleci/**/*.rb'

.circleci/linter_configs/.mdlrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# frozen_string_literal: true
2+
3+
all
4+
rule 'MD013', line_length: 500
5+
rule 'MD029', style: :ordered
6+
exclude_rule 'MD007'
7+
exclude_rule 'MD024'
Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
---
2+
13
require:
24
- rubocop-rspec
35
- rubocop-performance
46

57
AllCops:
6-
DisplayCopNames: true
7-
DisplayStyleGuide: true
8-
TargetRubyVersion: 2.5
8+
DisplayCopNames: true
9+
DisplayStyleGuide: true
10+
TargetRubyVersion: 2.5
11+
SuggestExtensions: false
912
NewCops: enable
1013

1114
# Metrics ---------------------------------------------------------------------
@@ -66,13 +69,13 @@ Layout/ClassStructure:
6669
- prepend
6770
- extend
6871
ExpectedOrder:
69-
- module_inclusion
70-
- constants
71-
- public_class_methods
72-
- initializer
73-
- public_methods
74-
- protected_methods
75-
- private_methods
72+
- module_inclusion
73+
- constants
74+
- public_class_methods
75+
- initializer
76+
- public_methods
77+
- protected_methods
78+
- private_methods
7679

7780
Layout/EmptyLineAfterGuardClause:
7881
Enabled: false
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
3+
extends: default
4+
5+
rules:
6+
line-length:
7+
max: 200

.circleci/scripts/release.sh

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# !/bin/sh
2+
set -e
3+
4+
GH_CLI_RELEASES_URL="https://github.com/cli/cli/releases"
5+
FILE_NAME="gh"
6+
BUILD_ARCHITECTURE="linux_amd64.deb"
7+
DELIMETER="_"
8+
PACKAGE_FILE="$FILE_NAME$DELIMETER$BUILD_ARCHITECTURE"
9+
10+
gh_cli_latest_release() {
11+
curl -sL -o /dev/null -w %{url_effective} "$GH_CLI_RELEASES_URL/latest" | rev | cut -f1 -d'/'| rev
12+
}
13+
14+
download_gh_cli() {
15+
test -z "$VERSION" && VERSION="$(gh_cli_latest_release)"
16+
test -z "$VERSION" && {
17+
echo "Unable to get GitHub CLI release." >&2
18+
exit 1
19+
}
20+
curl -s -L -o "$PACKAGE_FILE" "$GH_CLI_RELEASES_URL/download/$VERSION/$FILE_NAME$DELIMETER${VERSION:1}$DELIMETER$BUILD_ARCHITECTURE"
21+
}
22+
23+
install_gh_cli() {
24+
sudo dpkg -i "$PACKAGE_FILE"
25+
rm "$PACKAGE_FILE"
26+
}
27+
28+
get_release_candidate_version() {
29+
echo $(ruby -r rubygems -e "puts Gem::Specification::load('$(ls *.gemspec)').version")
30+
}
31+
32+
release_candidate_tag="v$(get_release_candidate_version)"
33+
34+
is_an_existing_github_release() {
35+
git fetch origin "refs/tags/$release_candidate_tag" >/dev/null 2>&1
36+
}
37+
38+
release_to_rubygems() {
39+
echo "Setting RubyGems publisher credentials..."
40+
./.circleci/scripts/set_publisher_credentials.sh
41+
echo "Preparation for release..."
42+
git config --global user.email ${PUBLISHER_EMAIL}
43+
git config --global user.name ${PUBLISHER_NAME}
44+
git stash
45+
git checkout develop
46+
gem install yard gem-ctags
47+
bundle install
48+
echo "Publishing new gem release to RubyGems..."
49+
rake release
50+
}
51+
52+
release_to_github() {
53+
echo "Downloading and installing latest gh cli..."
54+
download_gh_cli
55+
install_gh_cli
56+
echo "Publishing new release notes to GitHub..."
57+
gh release create "$release_candidate_tag" --generate-notes
58+
}
59+
60+
if is_an_existing_github_release
61+
then echo "Tag $release_candidate_tag already exists on GitHub. Skipping releasing flow..."
62+
else release_to_rubygems; release_to_github
63+
fi

0 commit comments

Comments
 (0)