├── bin ├── .gitkeep └── gitstamp ├── etc └── .gitkeep ├── lib ├── .gitkeep ├── gitstamp.rb └── gitstamp │ ├── version.rb │ ├── transaction.rb │ └── commit.rb ├── spec ├── .gitkeep └── spec_helper.rb ├── VERSION ├── .ruby-version ├── TODO.md ├── doc ├── examples │ └── .gitkeep └── .gitignore ├── CREDITS.md ├── .rspec ├── AUTHORS ├── .irbrc ├── Gemfile ├── .yardopts ├── .gitignore ├── CHANGES.md ├── .github └── workflows │ └── gitstamp.yaml ├── Rakefile ├── Makefile ├── UNLICENSE ├── README.md └── gitstamp.gemspec /bin/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /etc/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 0.1.0 2 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.7.1 2 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # To-Dos 2 | -------------------------------------------------------------------------------- /doc/examples/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CREDITS.md: -------------------------------------------------------------------------------- 1 | # Credits 2 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --require spec_helper 2 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | rdoc 2 | yard 3 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Arto Bendiken 2 | -------------------------------------------------------------------------------- /.irbrc: -------------------------------------------------------------------------------- 1 | require_relative 'lib/gitstamp' 2 | 3 | include Gitstamp 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec 3 | 4 | group :development do 5 | gem 'rake' 6 | gem 'rspec' 7 | gem 'rubocop', '~> 0.90.0', require: false 8 | gem 'yard' 9 | end 10 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --output-dir doc/yard 2 | --protected 3 | --no-private 4 | --hide-void-return 5 | --markup markdown 6 | --readme README.md 7 | - 8 | AUTHORS 9 | CHANGES.md 10 | CREDITS.md 11 | UNLICENSE 12 | VERSION 13 | -------------------------------------------------------------------------------- /lib/gitstamp.rb: -------------------------------------------------------------------------------- 1 | # This is free and unencumbered software released into the public domain. 2 | 3 | require_relative 'gitstamp/version' 4 | 5 | require_relative 'gitstamp/commit' 6 | require_relative 'gitstamp/transaction' 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # macOS 2 | .DS_Store 3 | 4 | # Visual Studio Code 5 | .vscode/ 6 | 7 | # Editor backup files 8 | *~ 9 | 10 | # Pandoc outputs 11 | *.html 12 | 13 | # Ruby artifacts 14 | .bundle 15 | .irb_history 16 | .yardoc 17 | Gemfile.lock 18 | *.gem 19 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | -------------------------------------------------------------------------------- /.github/workflows/gitstamp.yaml: -------------------------------------------------------------------------------- 1 | # See: https://github.com/weavery/gitstamp-action 2 | --- 3 | name: Gitstamp 4 | on: 5 | push: 6 | branches: 7 | - master 8 | jobs: 9 | gitstamp: 10 | runs-on: ubuntu-latest 11 | name: Timestamp commit with Gitstamp 12 | steps: 13 | - name: Clone repository 14 | uses: actions/checkout@v2 15 | - name: Submit Gitstamp transaction 16 | uses: weavery/gitstamp-action@v1 17 | with: 18 | wallet-key: ${{ secrets.GITSTAMP_KEYFILE }} 19 | commit-link: true 20 | -------------------------------------------------------------------------------- /lib/gitstamp/version.rb: -------------------------------------------------------------------------------- 1 | # This is free and unencumbered software released into the public domain. 2 | 3 | module Gitstamp 4 | module VERSION 5 | FILE = File.expand_path('../../VERSION', __dir__).freeze 6 | STRING = File.read(FILE).chomp.freeze 7 | MAJOR, MINOR, PATCH, EXTRA = STRING.split('.').map(&:to_i).freeze 8 | 9 | ## 10 | # @return [String] 11 | def self.to_s() STRING end 12 | 13 | ## 14 | # @return [String] 15 | def self.to_str() STRING end 16 | 17 | ## 18 | # @return [Array(Integer, Integer, Integer)] 19 | def self.to_a() [MAJOR, MINOR, PATCH].freeze end 20 | end # VERSION 21 | end # Gitstamp 22 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # This is free and unencumbered software released into the public domain. 2 | 3 | PROJECT = Dir['*.gemspec'].first.sub('.gemspec', '') 4 | VERSION = File.read('VERSION').chomp 5 | 6 | require_relative "lib/#{PROJECT}" 7 | 8 | require 'rake' 9 | 10 | task default: %w(install) 11 | 12 | file "#{PROJECT}-#{VERSION}.gem" => %w(build) 13 | 14 | desc "Build #{PROJECT}-#{VERSION}.gem from #{PROJECT}.gemspec" 15 | task :build => %W(#{PROJECT}.gemspec VERSION) do |t| 16 | sh "gem build #{t.prerequisites.first}" 17 | end 18 | 19 | desc "Install #{PROJECT}-#{VERSION}.gem locally" 20 | task :install => %W(#{PROJECT}-#{VERSION}.gem VERSION) do |t| 21 | sh "gem install #{t.prerequisites.first}" 22 | end 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # This is free and unencumbered software released into the public domain. 2 | 3 | VERSION := $(shell cat VERSION) 4 | VERSION_MAJOR = $(word 1,$(subst ., ,$(VERSION))) 5 | VERSION_MINOR = $(word 2,$(subst ., ,$(VERSION))) 6 | VERSION_PATCH = $(word 3,$(subst ., ,$(VERSION))) 7 | 8 | BUNDLE = bundle 9 | 10 | all: build 11 | 12 | build: Rakefile 13 | @$(BUNDLE) exec rake build 14 | 15 | test: check 16 | 17 | check: Rakefile 18 | @$(BUNDLE) exec rspec 19 | 20 | install: build 21 | @$(BUNDLE) exec rake install 22 | 23 | uninstall: 24 | @$(BUNDLE) exec rake uninstall 25 | 26 | clean: 27 | @rm -Rf *~ *.gem 28 | 29 | distclean: clean 30 | 31 | mostlyclean: clean 32 | 33 | maintainer-clean: clean 34 | 35 | .PHONY: all build test check install uninstall 36 | .PHONY: clean distclean mostlyclean maintainer-clean 37 | 38 | .SECONDARY: 39 | .SUFFIXES: 40 | -------------------------------------------------------------------------------- /lib/gitstamp/transaction.rb: -------------------------------------------------------------------------------- 1 | # This is free and unencumbered software released into the public domain. 2 | 3 | ## 4 | # A Gitstamp transaction is an Arweave transaction with specific tags. 5 | class Gitstamp::Transaction 6 | ## 7 | # The transaction's associated commit. 8 | # 9 | # @return [Commit] commit 10 | attr_reader :commit 11 | 12 | ## 13 | # Constructs a transaction from a commit. 14 | # 15 | # @param [Commit] commit 16 | # @return [void] 17 | def initialize(commit) 18 | @commit = commit 19 | end 20 | 21 | ## 22 | # Signs this transaction as originating from the given wallet. 23 | # 24 | # @param [Arweave::Wallet] wallet 25 | # @return [Arweave::Transaction] the signed Arweave transaction 26 | def sign(wallet) 27 | tx = Arweave::Transaction.new(data: @commit.message.to_s) 28 | @commit.to_tags.each do |name, value| 29 | tx.add_tag(name: name, value: value) 30 | end 31 | tx.sign(wallet) 32 | end 33 | 34 | ## 35 | # Submits this transaction to the Arweave network. 36 | # 37 | # @param [Arweave::Wallet] wallet 38 | # @return [String] the posted Arweave transaction ID 39 | def publish!(wallet) 40 | tx = self.sign(wallet) 41 | tx.commit 42 | tx.attributes[:id] 43 | end 44 | end # Gitstamp::Transaction 45 | -------------------------------------------------------------------------------- /UNLICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gitstamp Command-Line Interface (CLI) 2 | 3 | [![Project license](https://img.shields.io/badge/license-Public%20Domain-blue.svg)](https://unlicense.org) 4 | [![Ruby compatibility](https://img.shields.io/badge/ruby-2.4%2B-blue)](https://rubygems.org/gems/gitstamp) 5 | [![RubyGems gem](https://img.shields.io/gem/v/gitstamp.svg)](https://rubygems.org/gems/gitstamp) 6 | [![Discord](https://img.shields.io/discord/755852964513579099?label=discord)](https://discord.gg/6meRQ27) 7 | 8 | ## Prerequisites 9 | 10 | - [Ruby](https://www.ruby-lang.org/en/) 2.4+ 11 | 12 | ## Installation 13 | 14 | The tool can be installed quickly and easily on any computer that has [Ruby] 15 | available: 16 | 17 | ```bash 18 | $ gem install gitstamp 19 | ``` 20 | 21 | In case the command wasn't found after installation, you likely need to 22 | configure your `PATH` environment variable to include your [RubyGems] program 23 | path. 24 | 25 | ## See Also 26 | 27 | This repository is mirrored on [GitHub], [GitLab], and [Bitbucket]. 28 | 29 | [Ruby]: https://www.ruby-lang.org/en/ 30 | [RubyGems]: https://guides.rubygems.org/faqs/ 31 | [Arweave]: https://www.arweave.org 32 | [Arweave wallet]: https://www.arweave.org/wallet 33 | [GitHub]: https://github.com/weavery/gitstamp-cli 34 | [GitLab]: https://gitlab.com/weavery/gitstamp-cli 35 | [Bitbucket]: https://bitbucket.org/weavery/gitstamp-cli 36 | -------------------------------------------------------------------------------- /lib/gitstamp/commit.rb: -------------------------------------------------------------------------------- 1 | # This is free and unencumbered software released into the public domain. 2 | 3 | ## 4 | # A Gitstamp commit contains the Git commit message and relevant metadata. 5 | class Gitstamp::Commit < ::Struct.new(:id, :link, :author, :committer, :committer_date, :message, keyword_init: true) 6 | ## 7 | # Constructs a Gitstamp commit from a Git commit. 8 | # 9 | # @param [Rugged::Commit] git the Git commit object 10 | # @param [URI, #to_s] author an optional author URI override 11 | # @param [URI, #to_s] committer an optional committer URI override 12 | # @param [URI, #to_s] link an optional commit link URL 13 | # @return [Commit] 14 | def self.from_git(git, author: nil, committer: nil, link: nil) 15 | self.new( 16 | id: git.oid.to_s, 17 | link: link&.to_s, 18 | author: (author || "mailto:#{git.author[:email]}").to_s, 19 | committer: (committer || "mailto:#{git.committer[:email]}").to_s, 20 | committer_date: git.committer[:time], # preserves the timezone 21 | message: git.message.to_s, 22 | ) 23 | end 24 | 25 | ## 26 | # Returns the Arweave metadata tags for this commit. 27 | # 28 | # @return [Hash] 29 | def to_tags 30 | { 31 | 'Content-Type' => 'text/plain', 32 | 'App-Name' => 'Gitstamp', 33 | 'Git-Commit' => self.id.to_s, 34 | 'Git-Commit-Link' => self.link&.to_s, 35 | 'Git-Author' => self.author&.to_s, 36 | 'Git-Committer' => self.committer&.to_s, 37 | 'Git-Committer-Date' => self.committer_date&.strftime("%Y-%m-%dT%H:%M:%S%:z"), 38 | }.delete_if { |k, v| v.nil? } 39 | end 40 | end # Gitstamp::Commit 41 | -------------------------------------------------------------------------------- /gitstamp.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |gem| 2 | gem.version = File.read('VERSION').chomp 3 | gem.date = File.mtime('VERSION').strftime('%Y-%m-%d') 4 | 5 | gem.name = 'gitstamp' 6 | gem.homepage = 'https://gitstamp.dev' 7 | gem.license = 'Unlicense' 8 | gem.summary = 'Gitstamp Command-Line Interface (CLI)' 9 | gem.description = gem.summary 10 | 11 | gem.author = 'Arto Bendiken' 12 | gem.email = 'arto@bendiken.net' 13 | 14 | gem.metadata = { 15 | 'bug_tracker_uri' => 'https://github.com/weavery/gitstamp-cli/issues', 16 | 'changelog_uri' => 'https://github.com/weavery/gitstamp-cli/blob/master/CHANGES.md', 17 | 'documentation_uri' => 'https://www.rubydoc.info/github/weavery/gitstamp-cli/master', 18 | 'homepage_uri' => 'https://gitstamp.dev', 19 | 'source_code_uri' => 'https://github.com/weavery/gitstamp-cli', 20 | } 21 | 22 | gem.platform = Gem::Platform::RUBY 23 | gem.files = %w(AUTHORS CHANGES.md CREDITS.md README.md UNLICENSE VERSION) + Dir.glob('lib/**/*.rb') 24 | gem.bindir = %q(bin) 25 | gem.executables = %w(gitstamp) 26 | gem.require_paths = %w(lib) 27 | gem.extensions = %w() 28 | gem.test_files = %w() 29 | 30 | gem.required_ruby_version = '>= 2.4.0' 31 | gem.required_rubygems_version = '>= 2.6.8' # Ruby 2.4.0 32 | gem.requirements = [] 33 | gem.add_development_dependency 'rake', '>= 13' 34 | gem.add_development_dependency 'rspec', '>= 3.9' 35 | gem.add_development_dependency 'yard' , '>= 0.9' 36 | gem.add_runtime_dependency 'arweave', '~> 1.1' 37 | gem.add_runtime_dependency 'rugged', '~> 1.0' 38 | gem.add_runtime_dependency 'thor', '~> 1.0' 39 | gem.post_install_message = nil 40 | end 41 | -------------------------------------------------------------------------------- /bin/gitstamp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -W1 2 | # This is free and unencumbered software released into the public domain. 3 | 4 | require_relative '../lib/gitstamp' 5 | 6 | require 'arweave' # https://rubygems.org/gems/arweave 7 | require 'rugged' # https://rubygems.org/gems/rugged 8 | require 'thor' # https://rubygems.org/gems/thor 9 | 10 | require 'json' 11 | 12 | class CLI < Thor 13 | def self.exit_on_failure?() true end 14 | 15 | class_option :debug, aliases: '-d', type: :boolean, desc: "Enable debugging" 16 | class_option :verbose, aliases: '-v', type: :boolean, desc: "Be verbose (print warnings)" 17 | class_option :quiet, aliases: '-q', type: :boolean, desc: "Be quiet (silence non-fatal errors)" 18 | class_option :wallet, aliases: '-W', banner: 'FILE', desc: "Specify Arweave wallet FILE (in JWK format)" 19 | 20 | desc "publish COMMIT...", "Publish commits to Gitstamp" 21 | option :author, banner: 'URI', desc: "Override author URI (mailto: or https://)" 22 | option :committer, banner: 'URI', desc: "Override committer URI (mailto: or https://)" 23 | option :link, banner: 'URL', desc: "Include commit link URL (https://)" 24 | def publish(*commits) 25 | wallet = self.wallet 26 | author, committer, link = self.options[:author], self.options[:committer], self.options[:link] 27 | git = Rugged::Repository.new('.') 28 | commits = commits.empty? ? [git.head.target] : commits.map { |sha1| git.lookup(sha1) } 29 | commits.each do |commit| 30 | commit = Gitstamp::Commit.from_git(commit, author: author, committer: committer, link: link) 31 | warn commit.to_tags.inspect if debug? 32 | transaction_id = Gitstamp::Transaction.new(commit).publish!(wallet) 33 | puts "#{set_color(transaction_id, :green)}" unless quiet? 34 | end 35 | rescue => error 36 | raise error if debug? 37 | warn "#{$0}: #{set_color(error, :red)}" 38 | exit error.respond_to?(:exit_code) ? error.exit_code : -1 39 | end 40 | 41 | protected 42 | 43 | def wallet 44 | @wallet ||= begin 45 | wallet_path = self.options[:wallet] 46 | raise "wallet path required" if wallet_path.nil? 47 | raise "#{wallet_path}: wallet file not found" if !File.exist?(wallet_path) 48 | begin 49 | Arweave::Wallet.new(JSON.parse(File.read(wallet_path))) 50 | rescue JSON::ParserError => error 51 | raise "#{wallet_path}: #{error}" 52 | end 53 | end 54 | end 55 | 56 | def debug?() self.options[:debug] end 57 | def verbose?() self.options[:verbose] || self.debug? end 58 | def quiet?() self.options[:quiet] end 59 | end # CLI 60 | 61 | # Fix for https://github.com/erikhuda/thor/issues/398 62 | class Thor::Shell::Basic 63 | def print_wrapped(message, options = {}) 64 | indent = (options[:indent] || 0).to_i 65 | if indent.zero? 66 | self.stdout.puts message 67 | else 68 | message.each_line do |message_line| 69 | self.stdout.print ' ' * indent 70 | self.stdout.puts message_line.chomp 71 | end 72 | end 73 | end 74 | end # Thor::Shell::Basic 75 | 76 | CLI.start(ARGV) 77 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # This is free and unencumbered software released into the public domain. 2 | 3 | # This file was generated by the `rspec --init` command. Conventionally, all 4 | # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. 5 | # The generated `.rspec` file contains `--require spec_helper` which will cause 6 | # this file to always be loaded, without a need to explicitly require it in any 7 | # files. 8 | # 9 | # Given that it is always loaded, you are encouraged to keep this file as 10 | # light-weight as possible. Requiring heavyweight dependencies from this file 11 | # will add to the boot time of your test suite on EVERY test run, even for an 12 | # individual file that may not need all of that loaded. Instead, consider making 13 | # a separate helper file that requires the additional dependencies and performs 14 | # the additional setup, and require it from the spec files that actually need 15 | # it. 16 | # 17 | # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration 18 | RSpec.configure do |config| 19 | # rspec-expectations config goes here. You can use an alternate 20 | # assertion/expectation library such as wrong or the stdlib/minitest 21 | # assertions if you prefer. 22 | config.expect_with :rspec do |expectations| 23 | # This option will default to `true` in RSpec 4. It makes the `description` 24 | # and `failure_message` of custom matchers include text for helper methods 25 | # defined using `chain`, e.g.: 26 | # be_bigger_than(2).and_smaller_than(4).description 27 | # # => "be bigger than 2 and smaller than 4" 28 | # ...rather than: 29 | # # => "be bigger than 2" 30 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true 31 | end 32 | 33 | # rspec-mocks config goes here. You can use an alternate test double 34 | # library (such as bogus or mocha) by changing the `mock_with` option here. 35 | config.mock_with :rspec do |mocks| 36 | # Prevents you from mocking or stubbing a method that does not exist on 37 | # a real object. This is generally recommended, and will default to 38 | # `true` in RSpec 4. 39 | mocks.verify_partial_doubles = true 40 | end 41 | 42 | # This option will default to `:apply_to_host_groups` in RSpec 4 (and will 43 | # have no way to turn it off -- the option exists only for backwards 44 | # compatibility in RSpec 3). It causes shared context metadata to be 45 | # inherited by the metadata hash of host groups and examples, rather than 46 | # triggering implicit auto-inclusion in groups with matching metadata. 47 | config.shared_context_metadata_behavior = :apply_to_host_groups 48 | 49 | # The settings below are suggested to provide a good initial experience 50 | # with RSpec, but feel free to customize to your heart's content. 51 | =begin 52 | # This allows you to limit a spec run to individual examples or groups 53 | # you care about by tagging them with `:focus` metadata. When nothing 54 | # is tagged with `:focus`, all examples get run. RSpec also provides 55 | # aliases for `it`, `describe`, and `context` that include `:focus` 56 | # metadata: `fit`, `fdescribe` and `fcontext`, respectively. 57 | config.filter_run_when_matching :focus 58 | 59 | # Allows RSpec to persist some state between runs in order to support 60 | # the `--only-failures` and `--next-failure` CLI options. We recommend 61 | # you configure your source control system to ignore this file. 62 | config.example_status_persistence_file_path = "spec/examples.txt" 63 | 64 | # Limits the available syntax to the non-monkey patched syntax that is 65 | # recommended. For more details, see: 66 | # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ 67 | # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ 68 | # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode 69 | config.disable_monkey_patching! 70 | 71 | # This setting enables warnings. It's recommended, but in some cases may 72 | # be too noisy due to issues in dependencies. 73 | config.warnings = true 74 | 75 | # Many RSpec users commonly either run the entire suite or an individual 76 | # file, and it's useful to allow more verbose output when running an 77 | # individual spec file. 78 | if config.files_to_run.one? 79 | # Use the documentation formatter for detailed output, 80 | # unless a formatter has already been configured 81 | # (e.g. via a command-line flag). 82 | config.default_formatter = "doc" 83 | end 84 | 85 | # Print the 10 slowest examples and example groups at the 86 | # end of the spec run, to help surface which specs are running 87 | # particularly slow. 88 | config.profile_examples = 10 89 | 90 | # Run specs in random order to surface order dependencies. If you find an 91 | # order dependency and want to debug it, you can fix the order by providing 92 | # the seed, which is printed after each run. 93 | # --seed 1234 94 | config.order = :random 95 | 96 | # Seed global randomization in this process using the `--seed` CLI option. 97 | # Setting this allows you to use `--seed` to deterministically reproduce 98 | # test failures related to randomization by passing the same `--seed` value 99 | # as the one that triggered the failure. 100 | Kernel.srand config.seed 101 | =end 102 | end 103 | --------------------------------------------------------------------------------