├── lib ├── chandler.rb └── chandler │ ├── version.rb │ ├── logging.rb │ ├── tasks.rb │ ├── github │ ├── errors.rb │ ├── remote.rb │ └── client.rb │ ├── refinements │ ├── color.rb │ └── version_format.rb │ ├── configuration.rb │ ├── cli.rb │ ├── git.rb │ ├── github.rb │ ├── logger.rb │ ├── commands │ └── push.rb │ ├── cli │ └── parser.rb │ └── changelog.rb ├── exe └── chandler ├── .gitignore ├── bin ├── setup └── console ├── test ├── support │ ├── minitest_reporters.rb │ ├── mocha.rb │ ├── simplecov.rb │ └── logger_mocks.rb ├── chandler_test.rb ├── fixtures │ └── changelog │ │ ├── rst-definition.md │ │ ├── airbrussh.md │ │ ├── capistrano-fiftyfive.md │ │ ├── async.md │ │ ├── bootstrap-sass.md │ │ ├── actionview.md │ │ ├── capistrano.md │ │ ├── carrierwave.md │ │ ├── activeadmin.md │ │ └── rake.rdoc ├── minitest_helper.rb ├── exe_test.rb └── chandler │ ├── refinements │ ├── color_test.rb │ └── version_format_test.rb │ ├── logging_test.rb │ ├── tasks_test.rb │ ├── github │ ├── errors_test.rb │ ├── remote_test.rb │ └── client_test.rb │ ├── cli_test.rb │ ├── configuration_test.rb │ ├── cli │ └── parser_test.rb │ ├── git_test.rb │ ├── logger_test.rb │ ├── github_test.rb │ ├── commands │ └── push_test.rb │ └── changelog_test.rb ├── Guardfile ├── appveyor.yml ├── .travis.yml ├── Rakefile ├── Gemfile ├── LICENSE.txt ├── .rubocop.yml ├── chandler.gemspec ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dangerfile ├── CHANGELOG.md └── README.md /lib/chandler.rb: -------------------------------------------------------------------------------- 1 | require "chandler/version" 2 | 3 | module Chandler 4 | end 5 | -------------------------------------------------------------------------------- /lib/chandler/version.rb: -------------------------------------------------------------------------------- 1 | module Chandler 2 | VERSION = "0.9.0".freeze 3 | end 4 | -------------------------------------------------------------------------------- /exe/chandler: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "chandler/cli" 4 | Chandler::CLI.new.run 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | 5 | bundle install 6 | 7 | # Do any other automated setup that you need to do here 8 | -------------------------------------------------------------------------------- /test/support/minitest_reporters.rb: -------------------------------------------------------------------------------- 1 | require "minitest/reporters" 2 | 3 | Minitest::Reporters.use!( 4 | Minitest::Reporters::ProgressReporter.new, 5 | ENV, 6 | Minitest.backtrace_filter 7 | ) 8 | -------------------------------------------------------------------------------- /test/support/mocha.rb: -------------------------------------------------------------------------------- 1 | require "minitest" 2 | require "mocha/minitest" 3 | 4 | Mocha::Configuration.prevent(:stubbing_non_existent_method) 5 | Mocha::Configuration.warn_when(:stubbing_non_public_method) 6 | -------------------------------------------------------------------------------- /test/chandler_test.rb: -------------------------------------------------------------------------------- 1 | require "minitest_helper" 2 | require "chandler" 3 | 4 | class ChandlerTest < Minitest::Test 5 | def test_that_it_has_a_version_number 6 | refute_nil(::Chandler::VERSION) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | guard :minitest do 2 | # with Minitest::Unit 3 | watch(%r{^test/(.*)\/?(.*)_test\.rb$}) 4 | watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}#{m[2]}_test.rb" } 5 | watch(%r{^test/minitest_helper\.rb$}) { "test" } 6 | end 7 | -------------------------------------------------------------------------------- /test/fixtures/changelog/rst-definition.md: -------------------------------------------------------------------------------- 1 | 0.0.1 2 | - Added ACME project. 3 | 4 | 0.0.2-rc1 5 | - Pre-release. 6 | 7 | 0.0.2-dev-xyz 8 | - Dev pre-release. 9 | 10 | 0.0.2 11 | - Release. 12 | 13 | 0.1.0 14 | - Release 0.1 15 | 16 | v0.1.1 17 | - Update. 18 | 19 | -------------------------------------------------------------------------------- /test/minitest_helper.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__)) 2 | 3 | # Simplecov has to be loaded first 4 | require_relative("./support/simplecov") 5 | 6 | # Load everything else from test/support 7 | Dir[File.expand_path("../support/**/*.rb", __FILE__)].each { |rb| require(rb) } 8 | 9 | require "minitest/autorun" 10 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: '{build}' 2 | 3 | skip_tags: true 4 | 5 | environment: 6 | matrix: 7 | - ruby_version: "25" 8 | - ruby_version: "25-x64" 9 | 10 | install: 11 | - SET PATH=C:\Ruby%ruby_version%\bin;%PATH% 12 | - gem update --system 13 | - gem install bundler --no-document 14 | - bundle install --retry=3 15 | 16 | test_script: 17 | - bundle exec rake 18 | 19 | build: off 20 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "bundler/setup" 4 | require "chandler" 5 | 6 | # You can add fixtures and/or initialization code here to make experimenting 7 | # with your gem easier. You can also use a different console, if you like. 8 | 9 | # (If you use this, don't forget to add pry to your Gemfile!) 10 | # require "pry" 11 | # Pry.start 12 | 13 | require "irb" 14 | IRB.start 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: ruby 3 | cache: bundler 4 | rvm: 5 | - 2.3.8 6 | - 2.4.5 7 | - 2.5.3 8 | - 2.6.0 9 | - ruby-head 10 | before_install: 11 | - gem install bundler --conservative --no-document -v "~> 2.0" 12 | - gem install executable-hooks --conservative --no-document 13 | matrix: 14 | include: 15 | # Run Danger only once, on 2.6.0 16 | - rvm: 2.6.0 17 | script: bundle exec danger 18 | -------------------------------------------------------------------------------- /lib/chandler/logging.rb: -------------------------------------------------------------------------------- 1 | module Chandler 2 | # Assuming self responds to `config`, this mixin provides easy access to 3 | # logging methods by delegating to the configured Logger. 4 | # 5 | module Logging 6 | extend Forwardable 7 | private def_delegator :config, :logger 8 | private def_delegator :logger, :benchmark 9 | private def_delegator :logger, :error 10 | private def_delegator :logger, :info 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "rake/testtask" 3 | require "rubocop/rake_task" 4 | 5 | $LOAD_PATH.unshift File.expand_path("../lib", __FILE__) 6 | require "chandler/tasks" 7 | task "release:rubygem_push" => "chandler:push" 8 | 9 | Rake::TestTask.new(:test) do |t| 10 | t.libs << "test" 11 | t.libs << "lib" 12 | t.test_files = FileList["test/**/*_test.rb"] 13 | end 14 | 15 | RuboCop::RakeTask.new 16 | 17 | task :default => %i[test rubocop] 18 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | # Specify your gem's dependencies in chandler.gemspec 4 | gemspec 5 | 6 | # Optional development dependencies; requires bundler >= 1.10. 7 | # Note that these gems assume a Ruby environment greater than 2.2.5. 8 | # Install them using: 9 | # 10 | # bundle install --with guard 11 | # 12 | group :guard, :optional => true do 13 | gem "guard", ">= 2.2.2" 14 | gem "guard-minitest" 15 | gem "rb-fsevent" 16 | gem "terminal-notifier-guard" 17 | end 18 | -------------------------------------------------------------------------------- /test/support/simplecov.rb: -------------------------------------------------------------------------------- 1 | require "simplecov" 2 | 3 | if ENV["TRAVIS"] 4 | require "coveralls" 5 | SimpleCov.formatter = Coveralls::SimpleCov::Formatter 6 | end 7 | 8 | SimpleCov.start do 9 | # No need to report coverage metrics for the test code 10 | add_filter "test" 11 | end 12 | 13 | # Eager load the entire lib directory so that SimpleCov is able to report 14 | # accurate code coverage metrics. 15 | chandler_lib = File.expand_path("../../../lib", __FILE__) 16 | at_exit { Dir["#{chandler_lib}/**/*.rb"].each { |rb| require(rb) } } 17 | -------------------------------------------------------------------------------- /test/exe_test.rb: -------------------------------------------------------------------------------- 1 | require "minitest_helper" 2 | require "English" 3 | 4 | class ExeTest < Minitest::Test 5 | def test_chandler_is_executable_and_exits_with_success 6 | within_project_root do 7 | Bundler.with_clean_env do 8 | output = `bundle exec chandler --version` 9 | assert_equal("chandler version #{Chandler::VERSION}\n", output) 10 | assert($CHILD_STATUS.success?) 11 | end 12 | end 13 | end 14 | 15 | private 16 | 17 | def within_project_root(&block) 18 | Dir.chdir(File.expand_path("../..", __FILE__), &block) 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /test/support/logger_mocks.rb: -------------------------------------------------------------------------------- 1 | require "stringio" 2 | require "chandler/logger" 3 | 4 | module LoggerMocks 5 | class ColorfulStringIO < StringIO 6 | def tty? 7 | true 8 | end 9 | end 10 | 11 | private 12 | 13 | def stdout 14 | @stdout.string 15 | end 16 | 17 | def stderr 18 | @stderr.string 19 | end 20 | 21 | def new_logger 22 | @stderr = StringIO.new 23 | @stdout = StringIO.new 24 | Chandler::Logger.new(:stderr => @stderr, :stdout => @stdout) 25 | end 26 | 27 | def new_logger_with_color 28 | @stderr = ColorfulStringIO.new 29 | @stdout = ColorfulStringIO.new 30 | Chandler::Logger.new(:stderr => @stderr, :stdout => @stdout) 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/chandler/tasks.rb: -------------------------------------------------------------------------------- 1 | require "bundler/gem_helper" 2 | require "chandler/configuration" 3 | require "chandler/refinements/version_format" 4 | require "chandler/commands/push" 5 | require "rake" 6 | 7 | using Chandler::Refinements::VersionFormat 8 | 9 | namespace :chandler do 10 | desc "Push release notes for the current version to GitHub" 11 | task "push" do 12 | gemspec = Bundler::GemHelper.gemspec 13 | push = Chandler::Commands::Push.new( 14 | :tags => [gemspec.version.to_s.version_tag], 15 | :config => Chandler::Tasks.config 16 | ) 17 | push.call 18 | end 19 | end 20 | 21 | module Chandler 22 | module Tasks 23 | def self.config 24 | @configuration ||= Chandler::Configuration.new 25 | end 26 | 27 | def self.configure 28 | yield(config) 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /test/chandler/refinements/color_test.rb: -------------------------------------------------------------------------------- 1 | require "minitest_helper" 2 | require "chandler/refinements/color" 3 | 4 | class Chandler::Refinements::ColorTest < Minitest::Test 5 | using Chandler::Refinements::Color 6 | 7 | def test_color? 8 | refute("hello".color?) 9 | assert("\e[0;34;49mhello\e[0m".color?) 10 | end 11 | 12 | def test_strip_color 13 | assert_equal("hello", "hello".strip_color) 14 | assert_equal("hello", "\e[0;34;49mhello\e[0m".strip_color) 15 | end 16 | 17 | def test_red 18 | assert_equal("\e[0;31;49mhello\e[0m", "hello".red) 19 | end 20 | 21 | def test_green 22 | assert_equal("\e[0;32;49mhello\e[0m", "hello".green) 23 | end 24 | 25 | def test_blue 26 | assert_equal("\e[0;34;49mhello\e[0m", "hello".blue) 27 | end 28 | 29 | def test_gray 30 | assert_equal("\e[0;90;49mhello\e[0m", "hello".gray) 31 | end 32 | 33 | def test_grey 34 | assert_equal("\e[0;90;49mhello\e[0m", "hello".grey) 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /test/chandler/logging_test.rb: -------------------------------------------------------------------------------- 1 | require "minitest_helper" 2 | require "chandler/configuration" 3 | require "chandler/logging" 4 | 5 | class Chandler::LoggingTest < Minitest::Test 6 | class Subject 7 | include Chandler::Logging 8 | attr_reader :config 9 | def initialize 10 | @config = Chandler::Configuration.new 11 | end 12 | end 13 | 14 | def test_forwards_to_config_logger 15 | subject = Subject.new 16 | logger = subject.config.logger 17 | 18 | logger.expects(:benchmark) 19 | logger.expects(:error) 20 | logger.expects(:info) 21 | 22 | subject.send(:benchmark) 23 | subject.send(:error) 24 | subject.send(:info) 25 | end 26 | 27 | def test_methods_are_private 28 | subject = Subject.new 29 | 30 | assert_includes(subject.private_methods, :logger) 31 | assert_includes(subject.private_methods, :benchmark) 32 | assert_includes(subject.private_methods, :error) 33 | assert_includes(subject.private_methods, :info) 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/chandler/github/errors.rb: -------------------------------------------------------------------------------- 1 | module Chandler 2 | class GitHub 3 | Error = Class.new(StandardError) 4 | 5 | class InvalidRepository < Error 6 | def initialize(repository) 7 | @repository = repository 8 | end 9 | 10 | def message 11 | "Failed to find GitHub repository: #{@repository}.\n"\ 12 | "Verify you have permission to access it. Use the --github option to "\ 13 | "specify a different repository." 14 | end 15 | end 16 | 17 | class NetrcAuthenticationFailure < Error 18 | def message 19 | "GitHub authentication failed.\n"\ 20 | "Check that ~/.netrc is properly configured.\n"\ 21 | "For instructions, see: "\ 22 | "https://github.com/octokit/octokit.rb#using-a-netrc-file" 23 | end 24 | end 25 | 26 | class TokenAuthenticationFailure < Error 27 | def message 28 | "GitHub authentication failed.\n"\ 29 | "Check that the CHANDLER_GITHUB_API_TOKEN environment variable "\ 30 | "is correct." 31 | end 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/chandler/tasks_test.rb: -------------------------------------------------------------------------------- 1 | require "minitest_helper" 2 | require "rake" 3 | require "chandler/tasks" 4 | 5 | class Chandler::TasksTest < Minitest::Test 6 | def setup 7 | @gemspec = Gem::Specification.new 8 | @gemspec.stubs(:version => Gem::Version.new("1.0.2")) 9 | Bundler::GemHelper.stubs(:gemspec => @gemspec) 10 | end 11 | 12 | def test_defines_the_chandler_push_rake_task 13 | assert_instance_of(Rake::Task, Rake.application["chandler:push"]) 14 | end 15 | 16 | def test_push_task_calls_push_command_with_proper_arguments 17 | config = Chandler::Tasks.config 18 | push = Chandler::Commands::Push.new(:tags => [], :config => nil) 19 | 20 | Chandler::Commands::Push 21 | .expects(:new) 22 | .with(:tags => ["v1.0.2"], :config => config) 23 | .returns(push) 24 | 25 | push.expects(:call) 26 | 27 | Rake.application["chandler:push"].invoke 28 | end 29 | 30 | def test_configure_yields_config_object 31 | config = Chandler::Tasks.config 32 | assert_equal(config, Chandler::Tasks.configure { |c| c }) 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/chandler/github/errors_test.rb: -------------------------------------------------------------------------------- 1 | require "minitest_helper" 2 | require "chandler/github/errors" 3 | 4 | class Chandler::GitHub::ErrorsTest < Minitest::Test 5 | def test_invalid_repository 6 | invalid_repo = Chandler::GitHub::InvalidRepository.new("user/repo") 7 | assert_kind_of(Chandler::GitHub::Error, invalid_repo) 8 | assert_match(/failed to find/i, invalid_repo.message) 9 | assert_match("user/repo", invalid_repo.message) 10 | end 11 | 12 | def test_netrc_authentication_failure 13 | netrc_failure = Chandler::GitHub::NetrcAuthenticationFailure.new 14 | assert_kind_of(Chandler::GitHub::Error, netrc_failure) 15 | assert_match(/authentication failed/i, netrc_failure.message) 16 | assert_match(/netrc/, netrc_failure.message) 17 | end 18 | 19 | def test_token_authentication_failure 20 | token_failure = Chandler::GitHub::TokenAuthenticationFailure.new 21 | assert_kind_of(Chandler::GitHub::Error, token_failure) 22 | assert_match(/authentication failed/i, token_failure.message) 23 | assert_match("CHANDLER_GITHUB_API_TOKEN", token_failure.message) 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /test/chandler/github/remote_test.rb: -------------------------------------------------------------------------------- 1 | require "minitest_helper" 2 | require "chandler/github/remote" 3 | 4 | class Chandler::GitHub::RemoteTest < Minitest::Test 5 | def test_bare_repository_name 6 | repo = parse("mattbrictson/chandler") 7 | assert_equal("github.com", repo.host) 8 | assert_equal("mattbrictson/chandler", repo.repository) 9 | end 10 | 11 | def test_ssh_style_url 12 | repo = parse("git@github.com:mattbrictson/chandler.git") 13 | assert_equal("github.com", repo.host) 14 | assert_equal("mattbrictson/chandler", repo.repository) 15 | end 16 | 17 | def test_https_url 18 | repo = parse("https://github.com/mattbrictson/chandler.git") 19 | assert_equal("github.com", repo.host) 20 | assert_equal("mattbrictson/chandler", repo.repository) 21 | end 22 | 23 | def test_enterprise_ssh_style_url 24 | repo = parse("git@github.example.com:org/project.git") 25 | assert_equal("github.example.com", repo.host) 26 | assert_equal("org/project", repo.repository) 27 | end 28 | 29 | private 30 | 31 | def parse(url) 32 | Chandler::GitHub::Remote.parse(url) 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/chandler/github/remote.rb: -------------------------------------------------------------------------------- 1 | require "uri" 2 | 3 | module Chandler 4 | class GitHub 5 | # Assuming a git remote points to a public GitHub or a GitHub Enterprise 6 | # repository, this class parses the remote to obtain the host and repository 7 | # path. Supports SSH and HTTPS style git remotes. 8 | # 9 | # This class also handles parsing values passed into the `--github` command 10 | # line option, which may be a public GitHub repository name, like 11 | # "mattbrictson/chandler". 12 | # 13 | class Remote 14 | def self.parse(url) 15 | if (match = url.match(/@([^:]+):(.+)$/)) 16 | new(match[1], match[2]) 17 | else 18 | parsed_uri = URI(url) 19 | host = parsed_uri.host || "github.com" 20 | path = parsed_uri.path.sub(%r{^/+}, "") 21 | new(host, path) 22 | end 23 | end 24 | 25 | attr_reader :host, :path 26 | 27 | def initialize(host, path) 28 | @host = host.downcase 29 | @path = path 30 | end 31 | 32 | def repository 33 | path.sub(/\.git$/, "") 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Matt Brictson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | AllCops: 2 | TargetRubyVersion: 2.3 3 | DisplayCopNames: true 4 | DisplayStyleGuide: true 5 | Exclude: 6 | - "*.gemspec" 7 | - "vendor/**/*" 8 | 9 | Metrics/AbcSize: 10 | Exclude: 11 | - "test/**/*" 12 | 13 | Metrics/MethodLength: 14 | Exclude: 15 | - "test/**/*" 16 | 17 | Metrics/ClassLength: 18 | Exclude: 19 | - "test/**/*" 20 | 21 | Performance/Casecmp: 22 | Enabled: false 23 | 24 | Style/BarePercentLiterals: 25 | EnforcedStyle: percent_q 26 | 27 | Style/ClassAndModuleChildren: 28 | Enabled: false 29 | 30 | Style/Documentation: 31 | Enabled: false 32 | 33 | Style/DoubleNegation: 34 | Enabled: false 35 | 36 | Style/EndOfLine: 37 | EnforcedStyle: lf 38 | 39 | Style/FileName: 40 | Exclude: 41 | - "Dangerfile" 42 | 43 | Style/FrozenStringLiteralComment: 44 | Enabled: false 45 | 46 | Style/HashSyntax: 47 | EnforcedStyle: hash_rockets 48 | 49 | Style/IndentHeredoc: 50 | Enabled: false 51 | 52 | Style/SignalException: 53 | Exclude: 54 | - "Dangerfile" 55 | 56 | Style/SpaceAroundEqualsInParameterDefault: 57 | EnforcedStyle: no_space 58 | 59 | Style/StringLiterals: 60 | EnforcedStyle: double_quotes 61 | -------------------------------------------------------------------------------- /test/chandler/refinements/version_format_test.rb: -------------------------------------------------------------------------------- 1 | require "minitest_helper" 2 | require "chandler/refinements/version_format" 3 | 4 | class Chandler::Refinements::VersionFormatTest < Minitest::Test 5 | using Chandler::Refinements::VersionFormat 6 | 7 | def test_version? 8 | assert("1.0.1".version?) 9 | assert("v1.0.1".version?) 10 | assert("4.2.1.rc4".version?) 11 | assert("v4.2.1.rc4".version?) 12 | refute("wut".version?) 13 | refute("2 point oh".version?) 14 | end 15 | 16 | def test_version_number 17 | assert_equal("1.0.1", "1.0.1".version_number) 18 | assert_equal("1.0.1", "v1.0.1".version_number) 19 | assert_equal("4.2.1.rc4", "4.2.1.rc4".version_number) 20 | assert_equal("4.2.1.rc4", "v4.2.1.rc4".version_number) 21 | assert_nil("wut".version_number) 22 | assert_nil("2 point oh".version_number) 23 | end 24 | 25 | def test_version_tag 26 | assert_equal("v1.0.1", "1.0.1".version_tag) 27 | assert_equal("v1.0.1", "v1.0.1".version_tag) 28 | assert_equal("v4.2.1.rc4", "4.2.1.rc4".version_tag) 29 | assert_equal("v4.2.1.rc4", "v4.2.1.rc4".version_tag) 30 | assert_nil("wut".version_tag) 31 | assert_nil("2 point oh".version_tag) 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/chandler/refinements/color.rb: -------------------------------------------------------------------------------- 1 | module Chandler 2 | module Refinements 3 | # Monkey patch String to provide basic ANSI color support. 4 | # 5 | # "hello".color? # => false 6 | # "hello".blue # => "\e[0;34;49mhello\e[0m" 7 | # "hello".blue.color? # => true 8 | # "hello".blue.strip_color # "hello" 9 | # 10 | module Color 11 | ANSI_CODES = { 12 | :red => 31, 13 | :green => 32, 14 | :blue => 34, 15 | :gray => 90, 16 | :grey => 90 17 | }.freeze 18 | 19 | refine String do 20 | # Returns `true` if this String contains ANSI color sequences. 21 | def color? 22 | self != strip_color 23 | end 24 | 25 | # Returns a new String with ANSI color sequences removed. 26 | def strip_color 27 | gsub(/\e\[[0-9;]*m/, "") 28 | end 29 | 30 | # Define red, green, blue, etc. methods that return a copy of the 31 | # String that is wrapped in the corresponding ANSI color escape 32 | # sequence. 33 | ANSI_CODES.each do |name, code| 34 | define_method(name) do 35 | "\e[0;#{code};49m#{self}\e[0m" 36 | end 37 | end 38 | end 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /lib/chandler/configuration.rb: -------------------------------------------------------------------------------- 1 | require "chandler/changelog" 2 | require "chandler/git" 3 | require "chandler/github" 4 | require "chandler/logger" 5 | 6 | module Chandler 7 | class Configuration 8 | attr_accessor :changelog_path, :git_path, :dry_run, :tag_prefix, :logger, 9 | :environment 10 | attr_writer :github_repository 11 | 12 | def initialize 13 | @changelog_path = "CHANGELOG.md" 14 | @git_path = ".git" 15 | @logger = Chandler::Logger.new 16 | @dry_run = false 17 | @github_repository = nil 18 | end 19 | 20 | def dry_run? 21 | dry_run 22 | end 23 | 24 | def git 25 | @git ||= Chandler::Git.new(:path => git_path, :tag_mapper => tag_mapper) 26 | end 27 | 28 | def github 29 | @github ||= Chandler::GitHub.new( 30 | :repository => github_repository, 31 | :config => self 32 | ) 33 | end 34 | 35 | def changelog 36 | @changelog ||= Chandler::Changelog.new(:path => changelog_path) 37 | end 38 | 39 | def github_repository 40 | @github_repository || git.origin_remote 41 | end 42 | 43 | def tag_mapper 44 | return ->(tag) { tag } if tag_prefix.nil? 45 | ->(tag) { tag[/^#{Regexp.escape(tag_prefix)}(.*)/, 1] } 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/chandler/github/client.rb: -------------------------------------------------------------------------------- 1 | require "chandler/github/errors" 2 | require "delegate" 3 | require "octokit" 4 | require "uri" 5 | 6 | module Chandler 7 | class GitHub 8 | # A thin wrapper around Octokit::Client that adds support for automatic 9 | # GitHub Enterprise, .netrc, and ENV token-based authentication. 10 | # 11 | class Client < SimpleDelegator 12 | def initialize(host: "github.com", 13 | environment: ENV, 14 | octokit_client: Octokit::Client) 15 | options = {} 16 | options.merge!(detect_auth_option(environment)) 17 | options.merge!(detect_enterprise_endpoint(host)) 18 | super(octokit_client.new(options)) 19 | end 20 | 21 | def login! 22 | return if login 23 | raise netrc ? NetrcAuthenticationFailure : TokenAuthenticationFailure 24 | end 25 | 26 | private 27 | 28 | def detect_auth_option(env) 29 | if (token = env["CHANDLER_GITHUB_API_TOKEN"]) 30 | { :access_token => token } 31 | else 32 | { :netrc => true } 33 | end 34 | end 35 | 36 | def detect_enterprise_endpoint(host) 37 | return {} if host.downcase == "github.com" 38 | { :api_endpoint => "https://#{host}/api/v3/" } 39 | end 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/chandler/cli.rb: -------------------------------------------------------------------------------- 1 | require "chandler/cli/parser" 2 | require "chandler/commands/push" 3 | require "chandler/logging" 4 | require "forwardable" 5 | 6 | module Chandler 7 | # Handles constructing and invoking the appropriate chandler command 8 | # based on command line arguments and options provided by the CLI::Parser. 9 | # Essentially this is the "router" for the command-line app. 10 | # 11 | class CLI 12 | include Logging 13 | extend Forwardable 14 | def_delegator :@parser, :args 15 | def_delegator :@parser, :config 16 | 17 | def initialize(parser: Chandler::CLI::Parser.new(ARGV)) 18 | @parser = parser 19 | end 20 | 21 | def run 22 | command.call 23 | end 24 | 25 | private 26 | 27 | def command # rubocop:disable Metrics/MethodLength 28 | case (command = args.shift) 29 | when "push" 30 | push 31 | when nil 32 | error("Please specify a command") 33 | info(@parser.usage) 34 | exit(1) 35 | else 36 | error("Unrecognized command: #{command}") 37 | info(@parser.usage) 38 | exit(1) 39 | end 40 | end 41 | 42 | def push 43 | Chandler::Commands::Push.new( 44 | :tags => args.empty? ? config.git.version_tags : args, 45 | :config => config 46 | ) 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /chandler.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'chandler/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.required_ruby_version = ">= 2.1.0" 8 | 9 | spec.name = "chandler" 10 | spec.version = Chandler::VERSION 11 | spec.authors = ["Matt Brictson"] 12 | spec.email = ["chandler@mattbrictson.com"] 13 | 14 | spec.summary = "Syncs CHANGELOG entries to GitHub's release notes" 15 | spec.homepage = "https://github.com/mattbrictson/chandler" 16 | spec.license = "MIT" 17 | 18 | spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } 19 | spec.bindir = "exe" 20 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } 21 | spec.require_paths = ["lib"] 22 | 23 | spec.required_ruby_version = ">= 2.3.0" 24 | 25 | spec.add_dependency "netrc" 26 | spec.add_dependency "octokit", ">= 2.2.0" 27 | 28 | spec.add_development_dependency "bundler", "~> 2.0" 29 | spec.add_development_dependency "coveralls", "~> 0.8.20" 30 | spec.add_development_dependency "danger", "~> 6.0" 31 | spec.add_development_dependency "rake", "~> 12.0" 32 | spec.add_development_dependency "minitest", "~> 5.10" 33 | spec.add_development_dependency "minitest-reporters", "~> 1.1" 34 | spec.add_development_dependency "mocha", "~> 1.2" 35 | spec.add_development_dependency "rubocop", "0.48.1" 36 | end 37 | -------------------------------------------------------------------------------- /lib/chandler/refinements/version_format.rb: -------------------------------------------------------------------------------- 1 | module Chandler 2 | module Refinements 3 | # Monkey patch String to provide conveniences for identifying strings that 4 | # represent a version, and converting between between tags (e.g "v1.0.2") 5 | # and version numbers ("1.0.2"). 6 | # 7 | module VersionFormat 8 | refine String do 9 | # Does this string represent a version? 10 | # 11 | # "1.0.2".version? # => true 12 | # "v1.0.2".version? # => true 13 | # "nope".version? # => false 14 | # "".version? # => false 15 | # 16 | def version? 17 | !!version_number 18 | end 19 | 20 | # The version number portion of the string, with the optional "v" 21 | # prefix removed. 22 | # 23 | # "1.0.2".version_number # => "1.0.2" 24 | # "v1.0.2".version_number # => "1.0.2" 25 | # "nope".version_number # => nil 26 | # "".version_number # => nil 27 | # 28 | def version_number 29 | self[/^v?(#{Gem::Version::VERSION_PATTERN})$/, 1] 30 | end 31 | 32 | # The version number reformatted as a tag, by prefixing "v". 33 | # 34 | # "1.0.2".version_tag # => "v1.0.2" 35 | # "v1.0.2".version_tag # => "v1.0.2" 36 | # "nope".version_tag # => nil 37 | # "".version_tag # => nil 38 | # 39 | def version_tag 40 | number = version_number 41 | number && "v#{version_number}" 42 | end 43 | end 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all 4 | people who contribute through reporting issues, posting feature requests, 5 | updating documentation, submitting pull requests or patches, and other 6 | activities. 7 | 8 | We are committed to making participation in this project a harassment-free 9 | experience for everyone, regardless of level of experience, gender, gender 10 | identity and expression, sexual orientation, disability, personal appearance, 11 | body size, race, ethnicity, age, or religion. 12 | 13 | Examples of unacceptable behavior by participants include the use of sexual 14 | language or imagery, derogatory comments or personal attacks, trolling, public 15 | or private harassment, insults, or other unprofessional conduct. 16 | 17 | Project maintainers have the right and responsibility to remove, edit, or 18 | reject comments, commits, code, wiki edits, issues, and other contributions 19 | that are not aligned to this Code of Conduct. Project maintainers who do not 20 | follow the Code of Conduct may be removed from the project team. 21 | 22 | This code of conduct applies both within project spaces and in public spaces 23 | when an individual is representing the project or its community. 24 | 25 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 26 | reported by opening an issue or contacting one or more of the project 27 | maintainers. 28 | 29 | This Code of Conduct is adapted from the Contributor Covenant 30 | (http://contributor-covenant.org), version 1.1.0, available at 31 | http://contributor-covenant.org/version/1/1/0/ 32 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to chandler 2 | 3 | Have a feature idea, bug fix, or refactoring suggestion? Contributions are welcome! 4 | 5 | ## Pull requests 6 | 7 | 1. Check [Issues][] to see if your contribution has already been discussed and/or implemented. 8 | 2. If not, open an issue to discuss your contribution. I won't accept all changes and do not want to waste your time. 9 | 3. Once you have the :thumbsup:, fork the repo, make your changes, and open a PR. 10 | 4. Don't forget to add your contribution and credit yourself in `CHANGELOG.md`! 11 | 12 | ## Coding guidelines 13 | 14 | * This project has a coding style enforced by [RuboCop][]. Use hash rockets and double-quoted strings, and otherwise try to follow the [Ruby style guide][style]. 15 | * Writing tests is strongly encouraged! This project uses Minitest. 16 | 17 | ## Getting started 18 | 19 | After checking out the repo, run `bin/setup` to install dependencies. 20 | 21 | chandler offers the following development and testing commands: 22 | 23 | * `bin/console` loads your working copy of chandler into an irb session 24 | * `bundle exec chandler` runs your working copy of the chandler executable 25 | * `rake` executes all of chandler's tests and RuboCop checks 26 | 27 | A Guardfile is also present, so if you'd like to use Guard to do a TDD workflow, then: 28 | 29 | 1. Run `bundle install --with guard` to get the optional guard dependencies 30 | 2. Run `guard` to monitor the filesystem and automatically run tests as you work 31 | 32 | 33 | [Issues]: https://github.com/mattbrictson/chandler/issues 34 | [RuboCop]: https://github.com/bbatsov/rubocop 35 | [style]: https://github.com/bbatsov/ruby-style-guide 36 | -------------------------------------------------------------------------------- /test/chandler/cli_test.rb: -------------------------------------------------------------------------------- 1 | require "minitest_helper" 2 | require "chandler/cli" 3 | 4 | class Chandler::CLITest < Minitest::Test 5 | include LoggerMocks 6 | 7 | ParserStub = Struct.new(:args, :config, :usage) 8 | 9 | def setup 10 | @args = [] 11 | @config = Chandler::Configuration.new 12 | @config.logger = new_logger 13 | @parser = ParserStub.new(@args, @config, "usage") 14 | @cli = Chandler::CLI.new(:parser => @parser) 15 | end 16 | 17 | def test_missing_command_causes_exit 18 | error = assert_raises(SystemExit) { @cli.run } 19 | assert_equal(1, error.status) 20 | assert_match("Please specify a command", stderr) 21 | assert_match("usage", stdout) 22 | end 23 | 24 | def test_unrecognized_command_causes_exit 25 | @args << "blergh" 26 | error = assert_raises(SystemExit) { @cli.run } 27 | assert_equal(1, error.status) 28 | assert_match("Unrecognized command: blergh", stderr) 29 | assert_match("usage", stdout) 30 | end 31 | 32 | def test_push_is_invoked_for_all_git_tags_by_default 33 | @args << "push" 34 | @config.git.stubs(:version_tags => %w[v1.0.0 v1.0.1]) 35 | 36 | Chandler::Commands::Push 37 | .expects(:new) 38 | .with(:tags => %w[v1.0.0 v1.0.1], :config => @config) 39 | .returns(-> { "pushed" }) 40 | 41 | result = @cli.run 42 | assert_equal("pushed", result) 43 | end 44 | 45 | def test_push_is_invoked_for_specified_tag 46 | @args.concat(%w[push v1.0.2]) 47 | 48 | Chandler::Commands::Push 49 | .expects(:new) 50 | .with(:tags => %w[v1.0.2], :config => @config) 51 | .returns(-> { "pushed" }) 52 | 53 | result = @cli.run 54 | assert_equal("pushed", result) 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /test/chandler/configuration_test.rb: -------------------------------------------------------------------------------- 1 | require "minitest_helper" 2 | require "chandler/configuration" 3 | 4 | class Chandler::ConfigurationTest < Minitest::Test 5 | def setup 6 | @config = Chandler::Configuration.new 7 | end 8 | 9 | def test_defaults 10 | assert_equal("CHANGELOG.md", @config.changelog_path) 11 | assert_equal(".git", @config.git_path) 12 | assert_instance_of(Chandler::Logger, @config.logger) 13 | refute(@config.dry_run?) 14 | end 15 | 16 | def test_default_git 17 | @config.git_path = "../test/.git" 18 | git = @config.git 19 | assert_instance_of(Chandler::Git, git) 20 | assert_equal("../test/.git", git.path) 21 | assert_equal(:itself, git.tag_mapper.call(:itself)) 22 | end 23 | 24 | def test_prefixed_git 25 | @config.git_path = "../test/.git" 26 | @config.tag_prefix = "myapp-" 27 | mapper = @config.git.tag_mapper 28 | assert_nil(mapper.call("1.0.1")) 29 | assert_nil(mapper.call("whatever-2.5.2")) 30 | assert_equal("3.1.9", mapper.call("myapp-3.1.9")) 31 | end 32 | 33 | def test_explict_github_repository 34 | @config.github_repository = "test/repo" 35 | github = @config.github 36 | assert_instance_of(Chandler::GitHub, github) 37 | assert_equal("test/repo", github.repository) 38 | end 39 | 40 | def test_implict_github_repository 41 | git = @config.git 42 | git.expects(:origin_remote).returns("test/repo") 43 | github = @config.github 44 | assert_instance_of(Chandler::GitHub, github) 45 | assert_equal("test/repo", github.repository) 46 | end 47 | 48 | def test_changelog 49 | @config.changelog_path = "../test/history.md" 50 | changelog = @config.changelog 51 | assert_instance_of(Chandler::Changelog, changelog) 52 | assert_equal("../test/history.md", changelog.path) 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/chandler/git.rb: -------------------------------------------------------------------------------- 1 | require "chandler/refinements/version_format" 2 | require "open3" 3 | 4 | module Chandler 5 | # Uses the shell to execute git commands against a given .git directory. 6 | class Git 7 | using Chandler::Refinements::VersionFormat 8 | 9 | Error = Class.new(StandardError) 10 | attr_reader :path, :tag_mapper 11 | 12 | # Initializes the Git object with the path to the `.git` directory of the 13 | # desired git repository. 14 | # 15 | # Chandler::Git.new(:path => "/path/to/my/project/.git") 16 | # 17 | def initialize(path:, tag_mapper:) 18 | @path = path 19 | @tag_mapper = tag_mapper 20 | end 21 | 22 | # Uses `git tag -l` to obtain the list of tags, then returns the subset of 23 | # those tags that appear to be version numbers. 24 | # 25 | # version_tags # => ["v0.0.1", "v0.2.0", "v0.2.1", "v0.3.0"] 26 | # 27 | def version_tags 28 | tags = git("tag", "-l").lines.map(&:strip).select do |tag| 29 | version_part = tag_mapper.call(tag) 30 | version_part && version_part.version? 31 | end 32 | tags.sort_by { |t| Gem::Version.new(tag_mapper.call(t).version_number) } 33 | end 34 | 35 | # Uses `git remote -v` to list the remotes and returns the URL of the 36 | # first one labeled "origin". 37 | # 38 | # origin_remote # => "git@github.com:mattbrictson/chandler.git" 39 | # 40 | def origin_remote 41 | origin = git("remote", "-v").lines.grep(/^origin\s/).first 42 | origin && origin.split[1] 43 | end 44 | 45 | private 46 | 47 | def git(*args) 48 | capture("git", "--git-dir", path, *args) 49 | end 50 | 51 | def capture(*args) 52 | out, err, status = Open3.capture3(*args) 53 | return out if status.success? 54 | 55 | message = "Failed to execute: #{args.join(' ')}" 56 | message << "\n#{err}" unless err.nil? 57 | raise Error, message 58 | end 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /lib/chandler/github.rb: -------------------------------------------------------------------------------- 1 | require "chandler/github/client" 2 | require "chandler/github/errors" 3 | require "chandler/github/remote" 4 | 5 | module Chandler 6 | # A facade for performing GitHub API operations on a given GitHub repository 7 | # (specified as a git URL or as `owner/repo` format). Requires either that 8 | # "~/.netrc" is properly configured with GitHub credentials or an auth token 9 | # is available in the host environment at "CHANDLER_GITHUB_API_TOKEN"" 10 | # 11 | class GitHub 12 | attr_reader :repository, :config 13 | 14 | def initialize(repository:, config:) 15 | @repository = repository 16 | @remote = Remote.parse(repository) 17 | @config = config 18 | end 19 | 20 | def create_or_update_release(tag:, title:, description:) 21 | return if config.dry_run? 22 | 23 | release = existing_release(tag) 24 | return update_release(release, title, description) if release 25 | 26 | create_release(tag, title, description) 27 | rescue Octokit::NotFound 28 | raise InvalidRepository, repository 29 | end 30 | 31 | private 32 | 33 | attr_reader :remote 34 | 35 | def existing_release(tag) 36 | release = client.release_for_tag(remote.repository, tag) 37 | release.id.nil? ? nil : release 38 | rescue Octokit::NotFound 39 | nil 40 | end 41 | 42 | def update_release(release, title, desc) 43 | return if release_unchanged?(release, title, desc) 44 | client.update_release(release.url, :name => title, :body => desc) 45 | end 46 | 47 | def release_unchanged?(release, title, desc) 48 | release.name == title && release.body.to_s.strip == desc.strip 49 | end 50 | 51 | def create_release(tag, title, desc) 52 | client.create_release( 53 | remote.repository, tag, :name => title, :body => desc 54 | ) 55 | end 56 | 57 | def client 58 | @client ||= Client.new(:host => remote.host).tap(&:login!) 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /lib/chandler/logger.rb: -------------------------------------------------------------------------------- 1 | require "chandler/refinements/color" 2 | 3 | module Chandler 4 | # Similar to Ruby's standard Logger, but automatically removes ANSI color 5 | # from the logged messages if stdout and stderr do not support it. 6 | # 7 | class Logger 8 | using Chandler::Refinements::Color 9 | attr_accessor :stderr, :stdout 10 | 11 | def initialize(stderr: $stderr, stdout: $stdout) 12 | @stderr = stderr 13 | @stdout = stdout 14 | @color_enabled = nil 15 | end 16 | 17 | # Logs a message to stderr. Unless otherwise specified, the message will 18 | # be printed in red. 19 | def error(message) 20 | message = message.red unless message.color? 21 | puts(stderr, message) 22 | end 23 | 24 | # Logs a message to stdout. 25 | def info(message) 26 | puts(stdout, message) 27 | end 28 | 29 | # Logs a message to stdout, runs the given block, and then prints the time 30 | # it took to run the block. 31 | def benchmark(message) 32 | start = Time.now 33 | print(stdout, "#{message} ") 34 | result = yield 35 | duration = Time.now - start 36 | info("✔".green + format(" %0.3fs", duration).gray) 37 | result 38 | rescue 39 | info("✘".red) 40 | raise 41 | end 42 | 43 | private 44 | 45 | def print(io, message) 46 | message = message.strip_color unless color_enabled? 47 | io.print(message) 48 | end 49 | 50 | def puts(io, message) 51 | message = message.strip_color unless color_enabled? 52 | io.puts(message) 53 | end 54 | 55 | def color_enabled? 56 | @color_enabled = determine_color_support if @color_enabled.nil? 57 | @color_enabled 58 | end 59 | 60 | def determine_color_support 61 | if ENV["CLICOLOR_FORCE"] == "1" 62 | true 63 | elsif ENV["TERM"] == "dumb" 64 | false 65 | else 66 | tty?(stdout) && tty?(stderr) 67 | end 68 | end 69 | 70 | def tty?(io) 71 | io.respond_to?(:tty?) && io.tty? 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /test/chandler/github/client_test.rb: -------------------------------------------------------------------------------- 1 | require "minitest_helper" 2 | require "chandler/github/client" 3 | 4 | class Chandler::GitHub::ClientTest < Minitest::Test 5 | class FakeOctokitClient 6 | attr_reader :netrc, :access_token, :api_endpoint 7 | 8 | def initialize(options) 9 | @netrc = options.fetch(:netrc, false) 10 | @access_token = options[:access_token] 11 | @api_endpoint = options[:api_endpoint] if options[:api_endpoint] 12 | end 13 | 14 | def login 15 | "successful" 16 | end 17 | end 18 | 19 | class FakeOctokitClientWithError < FakeOctokitClient 20 | def login 21 | nil 22 | end 23 | end 24 | 25 | def test_uses_netrc_by_default 26 | client = Chandler::GitHub::Client.new(:octokit_client => FakeOctokitClient) 27 | assert(client.netrc) 28 | assert_nil(client.access_token) 29 | end 30 | 31 | def test_uses_access_token_from_env 32 | client = Chandler::GitHub::Client.new( 33 | :environment => { "CHANDLER_GITHUB_API_TOKEN" => "foo" }, 34 | :octokit_client => FakeOctokitClient 35 | ) 36 | assert_equal("foo", client.access_token) 37 | refute(client.netrc) 38 | end 39 | 40 | def test_doesnt_change_default_endpoint_for_public_github 41 | client = Chandler::GitHub::Client.new( 42 | :host => "github.com", 43 | :octokit_client => FakeOctokitClient 44 | ) 45 | assert_nil(client.api_endpoint) 46 | end 47 | 48 | def test_assigns_enterprise_endpoint 49 | client = Chandler::GitHub::Client.new( 50 | :host => "github.example.com", 51 | :octokit_client => FakeOctokitClient 52 | ) 53 | assert_equal("https://github.example.com/api/v3/", client.api_endpoint) 54 | end 55 | 56 | def test_raises_exception_if_netrc_fails 57 | assert_raises(Chandler::GitHub::NetrcAuthenticationFailure) do 58 | Chandler::GitHub::Client.new( 59 | :octokit_client => FakeOctokitClientWithError 60 | ).login! 61 | end 62 | end 63 | 64 | def test_raises_exception_if_access_token_fails 65 | assert_raises(Chandler::GitHub::TokenAuthenticationFailure) do 66 | Chandler::GitHub::Client.new( 67 | :environment => { "CHANDLER_GITHUB_API_TOKEN" => "foo" }, 68 | :octokit_client => FakeOctokitClientWithError 69 | ).login! 70 | end 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /lib/chandler/commands/push.rb: -------------------------------------------------------------------------------- 1 | require "chandler/logging" 2 | require "chandler/refinements/color" 3 | require "chandler/refinements/version_format" 4 | require "forwardable" 5 | 6 | module Chandler 7 | module Commands 8 | # Iterates over a given array of tags, fetches the corresponding notes 9 | # from the CHANGELOG, and creates (or updates) the release notes for that 10 | # tag on GitHub. 11 | class Push 12 | extend Forwardable 13 | def_delegators :config, :github, :changelog, :tag_mapper 14 | 15 | include Logging 16 | using Chandler::Refinements::Color 17 | using Chandler::Refinements::VersionFormat 18 | 19 | attr_reader :tags, :config 20 | 21 | def initialize(tags:, config:) 22 | @tags = tags 23 | @config = config 24 | end 25 | 26 | def call 27 | exit_with_warning if tags.empty? 28 | 29 | each_tag_with_version_and_notes do |tag, version, notes| 30 | github.create_or_update_release( 31 | :tag => tag, 32 | :title => version.version_number, 33 | :description => notes 34 | ) 35 | end 36 | end 37 | 38 | private 39 | 40 | def each_tag_with_version_and_notes 41 | width = tags.map(&:length).max 42 | tags.each do |tag| 43 | version, notes = changelog_version_and_notes_for_tag(tag) 44 | next if notes.nil? 45 | 46 | ellipsis = "…".ljust(1 + width - tag.length) 47 | benchmark("Push #{tag.blue}#{ellipsis}") do 48 | yield(tag, version, notes) 49 | end 50 | end 51 | end 52 | 53 | def exit_with_warning 54 | error("No version tags found.") 55 | exit(1) 56 | end 57 | 58 | def changelog_version_and_notes_for_tag(tag) 59 | version = tag_mapper.call(tag) 60 | notes = strip_surrounding_empty_lines(changelog.fetch(version)) 61 | [version, notes] 62 | rescue Chandler::Changelog::NoMatchingVersion 63 | info("Skip #{tag} (no #{version} entry in #{changelog.basename})".gray) 64 | nil 65 | end 66 | 67 | # Returns a new string with leading and trailing empty lines removed. A 68 | # line is empty if it is zero-length or contains only whitespace. 69 | def strip_surrounding_empty_lines(str) 70 | str.sub(/\A[[:space:]]*^/, "") 71 | .sub(/$[[:space:]]*\z/, "") 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /Dangerfile: -------------------------------------------------------------------------------- 1 | # Adapted from https://github.com/ruby-grape/danger/blob/master/Dangerfile 2 | # Q: What is a Dangerfile, anyway? A: See http://danger.systems/ 3 | 4 | # ------------------------------------------------------------------------------ 5 | # Additional pull request data 6 | # ------------------------------------------------------------------------------ 7 | project_name = github.pr_json["base"]["repo"]["name"] 8 | pr_number = github.pr_json["number"] 9 | pr_url = github.pr_json["_links"]["html"]["href"] 10 | 11 | # ------------------------------------------------------------------------------ 12 | # What changed? 13 | # ------------------------------------------------------------------------------ 14 | has_lib_changes = !git.modified_files.grep(/^lib/).empty? 15 | has_test_changes = !git.modified_files.grep(/^test/).empty? 16 | has_changelog_changes = git.modified_files.include?("CHANGELOG.md") 17 | 18 | # ------------------------------------------------------------------------------ 19 | # You've made changes to lib, but didn't write any tests? 20 | # ------------------------------------------------------------------------------ 21 | if has_lib_changes && !has_test_changes 22 | warn("There are code changes, but no corresponding tests. "\ 23 | "Please include tests if this PR introduces any modifications in "\ 24 | "#{project_name}'s behavior.", 25 | :sticky => false) 26 | end 27 | 28 | # ------------------------------------------------------------------------------ 29 | # Have you updated CHANGELOG.md? 30 | # ------------------------------------------------------------------------------ 31 | if !has_changelog_changes && has_lib_changes 32 | markdown <<-MARKDOWN 33 | Here's an example of a CHANGELOG.md entry (place it immediately under the `* Your contribution here!` line): 34 | 35 | ```markdown 36 | * [##{pr_number}](#{pr_url}): #{github.pr_title} - [@#{github.pr_author}](https://github.com/#{github.pr_author}) 37 | ``` 38 | MARKDOWN 39 | warn("Please update CHANGELOG.md with a description of your changes. "\ 40 | "If this PR is not a user-facing change (e.g. just refactoring), "\ 41 | "you can disregard this.", :sticky => false) 42 | end 43 | 44 | # ------------------------------------------------------------------------------ 45 | # Did you remove the CHANGELOG's "Your contribution here!" line? 46 | # ------------------------------------------------------------------------------ 47 | if has_changelog_changes 48 | unless IO.read("CHANGELOG.md") =~ /^\* Your contribution here/i 49 | fail( 50 | "Please put the `* Your contribution here!` line back into CHANGELOG.md.", 51 | :sticky => false 52 | ) 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /test/chandler/cli/parser_test.rb: -------------------------------------------------------------------------------- 1 | require "minitest_helper" 2 | require "chandler/cli/parser" 3 | 4 | class Chandler::CLI::ParserTest < Minitest::Test 5 | include LoggerMocks 6 | 7 | def test_usage 8 | parser = parse_arguments 9 | assert_match(/^Usage: chandler/, parser.usage) 10 | assert_match("chandler scans your git repository", parser.usage) 11 | assert_match("--git", parser.usage) 12 | assert_match("--github", parser.usage) 13 | assert_match("--changelog", parser.usage) 14 | assert_match("--dry-run", parser.usage) 15 | assert_match("--help", parser.usage) 16 | assert_match("--version", parser.usage) 17 | assert_match("--tag-prefix", parser.usage) 18 | end 19 | 20 | def test_args 21 | assert_equal([], parse_arguments.args) 22 | assert_equal([], parse_arguments("--dry-run").args) 23 | assert_equal(["push"], parse_arguments("push").args) 24 | assert_equal(["push"], parse_arguments("push", "--git=.git").args) 25 | assert_equal( 26 | ["push", "v1.0.1"], 27 | parse_arguments("push", "v1.0.1", "--dry-run").args 28 | ) 29 | end 30 | 31 | def test_config_is_unchanged_when_no_options_are_specified 32 | default_config = Chandler::Configuration.new 33 | config = parse_arguments.config 34 | 35 | assert_equal(config.dry_run?, default_config.dry_run?) 36 | assert_equal(config.git_path, default_config.git_path) 37 | assert_equal(config.github_repository, default_config.github_repository) 38 | assert_equal(config.changelog_path, default_config.changelog_path) 39 | end 40 | 41 | def test_config_is_changed_based_on_options 42 | args = %w[ 43 | push 44 | --git=../test/.git 45 | --github=test/repo 46 | --changelog=../test/changes.md 47 | --tag-prefix=myapp- 48 | --dry-run 49 | ] 50 | config = parse_arguments(*args).config 51 | 52 | assert(config.dry_run?) 53 | assert_equal("../test/.git", config.git_path) 54 | assert_equal("test/repo", config.github_repository) 55 | assert_equal("../test/changes.md", config.changelog_path) 56 | assert_equal("myapp-", config.tag_prefix) 57 | end 58 | 59 | def test_prints_version_and_exits 60 | exit = assert_raises(SystemExit) { parse_arguments("--version") } 61 | assert_equal(0, exit.status) 62 | assert_equal("chandler version #{Chandler::VERSION}\n", stdout) 63 | end 64 | 65 | def test_prints_usage_and_exits 66 | exit = assert_raises(SystemExit) { parse_arguments("--help") } 67 | assert_equal(0, exit.status) 68 | end 69 | 70 | private 71 | 72 | def parse_arguments(*args) 73 | config = Chandler::Configuration.new 74 | config.logger = new_logger 75 | Chandler::CLI::Parser.new(args, config) 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /test/chandler/git_test.rb: -------------------------------------------------------------------------------- 1 | require "minitest_helper" 2 | require "English" 3 | require "fileutils" 4 | require "tempfile" 5 | require "chandler/git" 6 | 7 | class Chandler::GitTest < Minitest::Test 8 | def test_version_tags_for_empty_repo 9 | create_git_repo 10 | assert_equal([], subject.version_tags) 11 | end 12 | 13 | def test_version_tags 14 | create_git_repo do 15 | git("commit --allow-empty -m 1") 16 | git("tag -a v0.1.0 -m 0.1.0") 17 | git("commit --allow-empty -m 2") 18 | git("tag -a v0.2.0 -m 0.2.0") 19 | git("commit --allow-empty -m 2") 20 | git("tag -a v0.11.0 -m 0.11.0") 21 | git("tag -a wip -m wip") 22 | end 23 | assert_equal(%w[v0.1.0 v0.2.0 v0.11.0], subject.version_tags) 24 | end 25 | 26 | def test_version_tags_with_prefix 27 | create_git_repo do 28 | git("commit --allow-empty -m 1") 29 | git("tag -a myapp-0.1.0 -m 0.1.0") 30 | git("commit --allow-empty -m 2") 31 | git("tag -a myapp-0.2.0 -m 0.2.0") 32 | git("commit --allow-empty -m 2") 33 | git("tag -a myapp-0.11.0 -m 0.11.0") 34 | git("tag -a wip -m wip") 35 | end 36 | mapper = ->(tag) { tag[/myapp-(.*)/, 1] } 37 | assert_equal( 38 | %w[myapp-0.1.0 myapp-0.2.0 myapp-0.11.0], 39 | subject(mapper).version_tags 40 | ) 41 | end 42 | 43 | def test_origin_remote_for_empty_repo 44 | create_git_repo 45 | assert_nil(subject.origin_remote) 46 | end 47 | 48 | def test_origin_remote 49 | create_git_repo do 50 | git("remote add upstream git@example.com:username/upstream") 51 | git("remote add origin git@example.com:username/origin") 52 | end 53 | assert_equal("git@example.com:username/origin", subject.origin_remote) 54 | end 55 | 56 | def test_error_includes_descriptive_message 57 | error = assert_raises(Chandler::Git::Error) do 58 | @git_path = "non-existent-path" 59 | subject.origin_remote 60 | end 61 | assert_match("Failed to execute: git", error.message) 62 | assert_match(/Not a git repository: 'non-existent-path'/i, error.message) 63 | end 64 | 65 | private 66 | 67 | def subject(mapper=->(tag) { tag }) 68 | @git ||= Chandler::Git.new(:path => @git_path, :tag_mapper => mapper) 69 | end 70 | 71 | def create_git_repo 72 | tempdir = Dir.mktmpdir("chandler-git-test-") 73 | @git_path = File.join(tempdir, ".git") 74 | at_exit { FileUtils.remove_entry(tempdir) } 75 | 76 | Dir.chdir(tempdir) do 77 | git("init") 78 | git("config user.email test@example.com") 79 | git("config user.name test") 80 | yield if block_given? 81 | end 82 | end 83 | 84 | def git(command) 85 | `git #{command}` 86 | raise unless $CHILD_STATUS.success? 87 | end 88 | end 89 | -------------------------------------------------------------------------------- /test/chandler/logger_test.rb: -------------------------------------------------------------------------------- 1 | require "minitest_helper" 2 | require "chandler/logger" 3 | 4 | class Chandler::LoggerTest < Minitest::Test 5 | include LoggerMocks 6 | 7 | def test_color_is_disabled_for_dumb_term 8 | ENV.stubs(:[]).returns(nil) 9 | ENV.stubs(:[]).with("TERM").returns("dumb") 10 | logger = new_logger_with_color 11 | logger.info("\e[0;31;49mhello\e[0m") 12 | assert_equal(stdout, "hello\n") 13 | end 14 | 15 | def test_color_can_be_forced_via_env 16 | ENV.stubs(:[]).returns(nil) 17 | ENV.stubs(:[]).with("CLICOLOR_FORCE").returns("1") 18 | logger = new_logger 19 | logger.info("\e[0;31;49mhello\e[0m") 20 | assert_equal(stdout, "\e[0;31;49mhello\e[0m\n") 21 | end 22 | 23 | def test_error_is_red_by_default 24 | logger = new_logger_with_color 25 | logger.error("hello") 26 | assert_equal("\e[0;31;49mhello\e[0m\n", stderr) 27 | assert_empty(stdout) 28 | end 29 | 30 | def test_color_is_passed_through_if_supported_by_output 31 | logger = new_logger_with_color 32 | 33 | logger.info("\e[0;32;49mhello\e[0m") 34 | logger.error("\e[0;32;49mhello\e[0m") 35 | 36 | assert_equal("\e[0;32;49mhello\e[0m\n", stdout) 37 | assert_equal("\e[0;32;49mhello\e[0m\n", stderr) 38 | end 39 | 40 | def test_color_is_stripped_if_not_supported_by_output 41 | logger = new_logger 42 | 43 | logger.info("\e[0;32;49mhello\e[0m") 44 | logger.error("\e[0;32;49mhello\e[0m") 45 | 46 | assert_equal("hello\n", stdout) 47 | assert_equal("hello\n", stderr) 48 | end 49 | 50 | def test_successful_benchmark 51 | block_executed = false 52 | logger = new_logger 53 | logger.benchmark("test") { block_executed = true } 54 | 55 | assert(block_executed) 56 | assert_match(/^test ✔ \d\.\d{3}s$/, stdout) 57 | assert_empty(stderr) 58 | end 59 | 60 | def test_successful_benchmark_in_color 61 | block_executed = false 62 | logger = new_logger_with_color 63 | logger.benchmark("test") { block_executed = true } 64 | 65 | assert(block_executed) 66 | assert_match( 67 | /^test \e\[0;32;49m✔\e\[0m\e\[0;90;49m \d\.\d{3}s\e\[0m$/, 68 | stdout 69 | ) 70 | assert_empty(stderr) 71 | end 72 | 73 | def test_failed_benchmark 74 | logger = new_logger 75 | 76 | assert_raises("boom!") do 77 | logger.benchmark("test") { raise "boom!" } 78 | end 79 | 80 | assert_match(/^test ✘$/, stdout) 81 | assert_empty(stderr) 82 | end 83 | 84 | def test_failed_benchmark_in_color 85 | logger = new_logger_with_color 86 | 87 | assert_raises("boom!") do 88 | logger.benchmark("test") { raise "boom!" } 89 | end 90 | 91 | assert_match( 92 | /^test \e\[0;31;49m✘\e\[0m$/, 93 | stdout 94 | ) 95 | assert_empty(stderr) 96 | end 97 | end 98 | -------------------------------------------------------------------------------- /test/fixtures/changelog/airbrussh.md: -------------------------------------------------------------------------------- 1 | # Airbrussh Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | Airbrussh is in a pre-1.0 state. This means that its APIs and behavior are subject to breaking changes without deprecation notices. Until 1.0, version numbers will follow a [Semver][]-ish `0.y.z` format, where `y` is incremented when new features or breaking changes are introduced, and `z` is incremented for lesser changes or bug fixes. 6 | 7 | ## [Unreleased] 8 | 9 | * Your contribution here! 10 | * Added Rubocop enforcement to Travis 11 | * Airbrussh now has decent test coverage, and is tested by Travis against a matrix of Ruby and SSHKit versions ([@robd](https://github.com/robd)) 12 | * Changes to support the new SSHKit formatter API, as introduced in [SSHKit #257](https://github.com/capistrano/sshkit/pull/257) ([@robd](https://github.com/robd)) 13 | 14 | ## [0.4.1][] (2015-05-06) 15 | 16 | * Fix `Marshal.dump` warnings by removing `deep_copy` workaround that it is no longer needed for the latest SSHKit ([#10](https://github.com/mattbrictson/airbrussh/issues/10)). 17 | 18 | ## [0.4.0][] (2015-05-03) 19 | 20 | * Changes to ensure compatibility with the upcoming version of SSHKit ([ec3122b](https://github.com/mattbrictson/airbrussh/commit/ec3122b101de53f2304723da842d5c8b6f70f4f3)). 21 | * Explicitly specify UTF-8 encoding for source files, for Ruby 1.9.3 compatibility ([#9](https://github.com/mattbrictson/airbrussh/issues/9)). 22 | 23 | ## [0.3.0][] (2015-03-28) 24 | 25 | * New `config.banner` option allows startup message to be disabled or changed (suggestion from [@justindowning](https://github.com/justindowning)) 26 | * New `config.command_output` option gives full control of whether airbrussh shows or hides the stderr and stdout data received from remote commands; see the usage section of the README for further explanation (suggestion from [@carlesso](https://github.com/carlesso)) 27 | 28 | ## [0.2.1][] (2015-03-02) 29 | 30 | * Un-pin SSHKit dependency now that SSHKit 1.7.1 has been released. 31 | 32 | ## [0.2.0][] (2015-03-02) 33 | 34 | * Pin SSHKit dependency at `~> 1.6.1` to avoid a [bug in 1.7.0](https://github.com/capistrano/sshkit/issues/226) that causes command exit statuses to be omitted from the log. 35 | 36 | ## 0.0.1 (2015-02-19) 37 | 38 | * Initial release 39 | 40 | [Semver]: http://semver.org 41 | [Unreleased]: https://github.com/mattbrictson/airbrussh/compare/v0.4.1...HEAD 42 | [0.4.1]: https://github.com/mattbrictson/airbrussh/compare/v0.4.0...v0.4.1 43 | [0.4.0]: https://github.com/mattbrictson/airbrussh/compare/v0.3.0...v0.4.0 44 | [0.3.0]: https://github.com/mattbrictson/airbrussh/compare/v0.2.1...v0.3.0 45 | [0.2.1]: https://github.com/mattbrictson/airbrussh/compare/v0.2.0...v0.2.1 46 | [0.2.0]: https://github.com/mattbrictson/airbrussh/compare/v0.0.1...v0.2.0 47 | -------------------------------------------------------------------------------- /lib/chandler/cli/parser.rb: -------------------------------------------------------------------------------- 1 | require "chandler/configuration" 2 | require "chandler/logging" 3 | require "chandler/version" 4 | require "optparse" 5 | 6 | module Chandler 7 | class CLI 8 | class Parser 9 | include Logging 10 | attr_reader :args, :config 11 | 12 | def initialize(args, config=Chandler::Configuration.new) 13 | @args = args 14 | @config = config 15 | parse_options 16 | end 17 | 18 | def usage 19 | option_parser.to_s 20 | end 21 | 22 | private 23 | 24 | def parse_options 25 | unprocessed = [] 26 | until args.empty? 27 | option_parser.order!(args) 28 | unprocessed << args.shift 29 | end 30 | @args = unprocessed.compact 31 | end 32 | 33 | # rubocop:disable Metrics/AbcSize 34 | # rubocop:disable Metrics/MethodLength 35 | # rubocop:disable Metrics/BlockLength 36 | def option_parser 37 | OptionParser.new do |opts| 38 | opts.banner = "Usage: chandler push [tag] [options]" 39 | opts.separator("") 40 | opts.separator(summary) 41 | opts.separator("") 42 | 43 | opts.on("--git=[PATH]", "Path to .git directory") do |p| 44 | config.git_path = p 45 | end 46 | 47 | opts.on("--github=[URL]", 48 | "GitHub repository URL or owner/repo") do |u| 49 | config.github_repository = u 50 | end 51 | 52 | opts.on("--changelog=[PATH]", 53 | "Path to CHANGELOG Markdown file") do |p| 54 | config.changelog_path = p 55 | end 56 | 57 | opts.on("--tag-prefix=[PREFIX]", 58 | "Use PREFIX to identify Git version tags") do |p| 59 | config.tag_prefix = p 60 | end 61 | 62 | opts.on("--dry-run", 63 | "Simulate, but don’t actually push to GitHub") do |d| 64 | config.dry_run = d 65 | end 66 | 67 | opts.on("-h", "--help", "Show this help message") do 68 | info(opts.to_s) 69 | exit 70 | end 71 | 72 | opts.on("-v", "--version", "Print the chandler version number") do 73 | info("chandler version #{Chandler::VERSION}") 74 | exit 75 | end 76 | end 77 | end 78 | 79 | def summary 80 | <<-SUMMARY 81 | chandler scans your git repository for version tags (e.g. `v1.0.2`), parses out 82 | the corresponding release notes for those tags from your CHANGELOG, and uploads 83 | those notes to the GitHub releases area via the GitHub API. 84 | 85 | chandler will use reasonable defaults and inferences to configure itself. 86 | If chandler doesn’t work for you out of the box, override the configuration 87 | using these options. 88 | SUMMARY 89 | end 90 | end 91 | end 92 | end 93 | -------------------------------------------------------------------------------- /test/chandler/github_test.rb: -------------------------------------------------------------------------------- 1 | require "minitest_helper" 2 | require "chandler/configuration" 3 | require "chandler/github" 4 | 5 | class Chandler::GitHubTest < Minitest::Test 6 | def setup 7 | @config = Chandler::Configuration.new 8 | 9 | @client = Chandler::GitHub::Client.new 10 | @client.stubs(:login).returns("username") 11 | Chandler::GitHub::Client 12 | .stubs(:new) 13 | .with(:host => "github.com") 14 | .returns(@client) 15 | 16 | @github = Chandler::GitHub.new(:repository => "repo", :config => @config) 17 | end 18 | 19 | def test_dry_run_disables_all_api_calls 20 | @client.expects(:release_for_tag).never 21 | @client.expects(:create_release).never 22 | @client.expects(:update_release).never 23 | 24 | @config.dry_run = true 25 | @github.create_or_update_release( 26 | :tag => "v1.0.2", 27 | :title => "1.0.2", 28 | :description => "Fix a bug" 29 | ) 30 | end 31 | 32 | def test_no_update_performed_if_release_has_not_changed 33 | tag = "v1.0.2" 34 | title = "1.0.2" 35 | desc = "desc" 36 | release = stub(:id => "id", :name => title, :body => desc) 37 | 38 | @client.expects(:release_for_tag).with("repo", tag).returns(release) 39 | @client.expects(:create_release).never 40 | @client.expects(:update_release).never 41 | 42 | @github.create_or_update_release( 43 | :tag => tag, 44 | :title => title, 45 | :description => desc 46 | ) 47 | end 48 | 49 | def test_update_performed_if_release_exists_and_is_different 50 | tag = "v1.0.2" 51 | title = "1.0.2" 52 | desc = "desc" 53 | release = stub(:id => "id", :url => "url", :name => title, :body => "old") 54 | 55 | @client.expects(:release_for_tag).with("repo", tag).returns(release) 56 | @client.expects(:update_release) 57 | .with("url", :name => title, :body => desc) 58 | @client.expects(:create_release).never 59 | 60 | @github.create_or_update_release( 61 | :tag => tag, 62 | :title => title, 63 | :description => desc 64 | ) 65 | end 66 | 67 | def test_create_performed_if_existing_release_404s 68 | tag = "v1.0.2" 69 | title = "1.0.2" 70 | desc = "desc" 71 | 72 | @client.expects(:release_for_tag) 73 | .with("repo", tag) 74 | .raises(Octokit::NotFound) 75 | 76 | @client.expects(:create_release) 77 | .with("repo", tag, :name => title, :body => desc) 78 | 79 | @client.expects(:update_release).never 80 | 81 | @github.create_or_update_release( 82 | :tag => tag, 83 | :title => title, 84 | :description => desc 85 | ) 86 | end 87 | 88 | def test_create_performed_if_existing_release_has_nil_id 89 | tag = "v1.0.2" 90 | title = "1.0.2" 91 | desc = "desc" 92 | release = stub(:id => nil) 93 | 94 | @client.expects(:release_for_tag).with("repo", tag).returns(release) 95 | 96 | @client.expects(:create_release) 97 | .with("repo", tag, :name => title, :body => desc) 98 | 99 | @client.expects(:update_release).never 100 | 101 | @github.create_or_update_release( 102 | :tag => tag, 103 | :title => title, 104 | :description => desc 105 | ) 106 | end 107 | 108 | def test_raises_exception_if_repo_doesnt_exist 109 | @client.expects(:release_for_tag).raises(Octokit::NotFound) 110 | @client.expects(:create_release).raises(Octokit::NotFound) 111 | 112 | assert_raises(Chandler::GitHub::InvalidRepository) do 113 | @github.create_or_update_release( 114 | :tag => "v1.0.2", 115 | :title => "1.0.2", 116 | :description => "desc" 117 | ) 118 | end 119 | end 120 | end 121 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # chandler Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | chandler is in a pre-1.0 state. This means that its APIs and behavior are subject to breaking changes without deprecation notices. Until 1.0, version numbers will follow a [Semver][]-ish `0.y.z` format, where `y` is incremented when new features or breaking changes are introduced, and `z` is incremented for lesser changes or bug fixes. 6 | 7 | ## [Unreleased][] 8 | 9 | * Your contribution here! 10 | 11 | ## [0.9.0][] (2019-02-10) 12 | 13 | * [#45](https://github.com/mattbrictson/chandler/pull/45): Submit link references together with the release notes for each version so that links are always properly rendered - [@deivid-rodriguez](https://github.com/deivid-rodriguez) 14 | 15 | ## [0.8.0][] (2019-01-26) 16 | 17 | * **Drop support for EOL Rubies.** Chandler now requires Ruby >= 2.3. 18 | 19 | ## [0.7.0][] (2016-12-23) 20 | 21 | * [#23](https://github.com/mattbrictson/chandler/pull/23): Fix warnings reported when using Rake 12.0 - [@mattbrictson](https://github.com/mattbrictson) 22 | * [#21](https://github.com/mattbrictson/chandler/pull/21): Remove --debug flag since it is not used anywhere - [@mattbrictson](https://github.com/mattbrictson) 23 | 24 | ## [0.6.0][] (2016-11-09) 25 | 26 | * [#19](https://github.com/mattbrictson/chandler/pull/19): Add GitHub Enterprise support - [@mattbrictson](https://github.com/mattbrictson) 27 | 28 | ## [0.5.0][] (2016-10-07) 29 | 30 | * Adds support for using `CHANDLER_GITHUB_API_TOKEN` to authenticate your API requests - Orta 31 | 32 | ## [0.4.0][] (2016-09-23) 33 | 34 | * Support for reStructuredText `definition-list` style CHANGELOG layouts. 35 | 36 | ## [0.3.1][] (2016-05-13) 37 | 38 | * Fix a bug where the formatting of certain Markdown release notes were 39 | inadvertently altered due to stripping indentation off the first line of the 40 | text. 41 | 42 | ## [0.3.0][] (2016-03-22) 43 | 44 | * Support Markdown "setext" style h1-level headings [#11](https://github.com/mattbrictson/chandler/pull/11) 45 | 46 | ## [0.2.0][] (2016-02-19) 47 | 48 | * Chandler now understands versions at Markdown/Rdoc h1-level headings (previously only h2 and h3 were searched). 49 | * If Chandler can't find any version tags, print an error message rather than exiting silently. 50 | * If Chandler can't find a version in your CHANGELOG, it will log a warning rather than exiting with an uncaught exception. 51 | * Add `--tag-prefix` option to allow for other Git version tag formats (e.g. `myapp-v1.0.0`; see [#3](https://github.com/mattbrictson/chandler/issues/3)) 52 | 53 | ## [0.1.2][] (2015-10-26) 54 | 55 | * Fix Windows test failures introduced in 0.1.1 56 | 57 | ## [0.1.1][] (2015-10-26) 58 | 59 | * Work around parsing issues caused by non-breaking spaces in change logs (e.g. SSHKit) 60 | 61 | ## 0.1.0 (2015-06-19) 62 | 63 | * Initial release 64 | 65 | [Semver]: http://semver.org 66 | [Unreleased]: https://github.com/mattbrictson/chandler/compare/v0.9.0...HEAD 67 | [0.9.0]: https://github.com/mattbrictson/chandler/compare/v0.8.0...v0.9.0 68 | [0.8.0]: https://github.com/mattbrictson/chandler/compare/v0.7.0...v0.8.0 69 | [0.7.0]: https://github.com/mattbrictson/chandler/compare/v0.6.0...v0.7.0 70 | [0.6.0]: https://github.com/mattbrictson/chandler/compare/v0.5.0...v0.6.0 71 | [0.5.0]: https://github.com/mattbrictson/chandler/compare/v0.4.0...v0.5.0 72 | [0.4.0]: https://github.com/mattbrictson/chandler/compare/v0.3.1...v0.4.0 73 | [0.3.1]: https://github.com/mattbrictson/chandler/compare/v0.3.0...v0.3.1 74 | [0.3.0]: https://github.com/mattbrictson/chandler/compare/v0.2.0...v0.3.0 75 | [0.2.0]: https://github.com/mattbrictson/chandler/compare/v0.1.2...v0.2.0 76 | [0.1.2]: https://github.com/mattbrictson/chandler/compare/v0.1.1...v0.1.2 77 | [0.1.1]: https://github.com/mattbrictson/chandler/compare/v0.1.0...v0.1.1 78 | -------------------------------------------------------------------------------- /test/chandler/commands/push_test.rb: -------------------------------------------------------------------------------- 1 | require "minitest_helper" 2 | require "chandler/configuration" 3 | require "chandler/github" 4 | require "chandler/commands/push" 5 | 6 | class Chandler::Commands::PushTest < Minitest::Test 7 | include LoggerMocks 8 | 9 | def setup 10 | @github = Chandler::GitHub.new( 11 | :repository => "", 12 | :config => nil 13 | ) 14 | @github.stubs(:create_or_update_release) 15 | 16 | @config = Chandler::Configuration.new 17 | @config.logger = new_logger 18 | @config.stubs(:github => @github) 19 | @config.changelog.stubs(:fetch => "notes") 20 | end 21 | 22 | def test_changelog_is_used_to_obtain_notes 23 | @config.changelog.expects(:fetch).with("v1").returns("notes") 24 | push = Chandler::Commands::Push.new(:tags => %w[v1], :config => @config) 25 | push.call 26 | end 27 | 28 | def test_changelog_is_used_to_obtain_notes_using_tag_mapper 29 | @config.stubs(:tag_mapper).returns(->(_tag) { "foo" }) 30 | @config.changelog.expects(:fetch).with("foo").returns("notes") 31 | push = Chandler::Commands::Push.new(:tags => %w[v1], :config => @config) 32 | push.call 33 | end 34 | 35 | def test_github_is_used_to_create_or_update_releases 36 | @github 37 | .expects(:create_or_update_release) 38 | .with(:tag => "v1", :title => "1", :description => "notes") 39 | 40 | @github 41 | .expects(:create_or_update_release) 42 | .with(:tag => "v2", :title => "2", :description => "notes") 43 | 44 | push = Chandler::Commands::Push.new(:tags => %w[v1 v2], :config => @config) 45 | push.call 46 | end 47 | 48 | def test_tag_prefix_is_removed_from_title_when_pushing_to_github 49 | @config.tag_prefix = "app-" 50 | @github 51 | .expects(:create_or_update_release) 52 | .with(:tag => "app-1", :title => "1", :description => "notes") 53 | 54 | push = Chandler::Commands::Push.new(:tags => %w[app-1], :config => @config) 55 | push.call 56 | end 57 | 58 | def test_leading_and_trailing_blank_lines_are_stripped_when_pushing_to_github 59 | @config.changelog 60 | .expects(:fetch).with("v1") 61 | .returns("\n\n * one\n\n * two\n\n") 62 | @github.unstub(:create_or_update_release) 63 | @github 64 | .expects(:create_or_update_release) 65 | .with(:tag => "v1", :title => "1", :description => " * one\n\n * two") 66 | 67 | push = Chandler::Commands::Push.new(:tags => %w[v1], :config => @config) 68 | push.call 69 | end 70 | 71 | def test_progress_is_pretty_printed_to_stdout 72 | push = Chandler::Commands::Push.new( 73 | :tags => %w[v1 v2.0.2 v99.1.18], 74 | :config => @config 75 | ) 76 | push.call 77 | 78 | assert_match("Push v1… ✔", stdout) 79 | assert_match("Push v2.0.2… ✔", stdout) 80 | assert_match("Push v99.1.18… ✔", stdout) 81 | end 82 | 83 | def test_skipped_tag_is_printed_to_stdout 84 | @config.changelog 85 | .stubs(:fetch) 86 | .with("v2.0.2") 87 | .raises(Chandler::Changelog::NoMatchingVersion) 88 | 89 | push = Chandler::Commands::Push.new( 90 | :tags => %w[v1 v2.0.2 v99.1.18], 91 | :config => @config 92 | ) 93 | push.call 94 | 95 | assert_match("Push v1… ✔", stdout) 96 | refute_match("Push v2.0.2… ✔", stdout) 97 | assert_match("Skip v2.0.2 (no v2.0.2 entry in CHANGELOG.md)", stdout) 98 | assert_match("Push v99.1.18… ✔", stdout) 99 | end 100 | 101 | def test_exits_with_warning_if_no_tags 102 | push = Chandler::Commands::Push.new(:tags => [], :config => @config) 103 | 104 | Mocha::Configuration.allow(:stubbing_non_public_method) do 105 | push.expects(:exit).with(1).throws(:exited) 106 | end 107 | 108 | assert_throws(:exited) { push.call } 109 | assert_match(/no version tags/i, stderr) 110 | end 111 | end 112 | -------------------------------------------------------------------------------- /lib/chandler/changelog.rb: -------------------------------------------------------------------------------- 1 | require "chandler/refinements/version_format" 2 | 3 | module Chandler 4 | # Responsible for parsing a CHANGELOG into a hash of release notes keyed 5 | # by version number. Release notes for a particular version or tag can be 6 | # accessed using the `fetch` method. 7 | class Changelog 8 | using Chandler::Refinements::VersionFormat 9 | 10 | NoMatchingVersion = Class.new(StandardError) 11 | 12 | HEADING_PATTERNS = [ 13 | /^#[[:space:]]+.*\n/, # Markdown "atx" style 14 | /^##[[:space:]]+.*\n/, 15 | /^###[[:space:]]+.*\n/, 16 | /^=[[:space:]]+.*\n/, # Rdoc style 17 | /^==[[:space:]]+.*\n/, 18 | /^===[[:space:]]+.*\n/, 19 | /^\S.*\n=+\n/, # Markdown "Setext" style 20 | /^\S.*\n-+\n/, 21 | /^[vr]?[0-9]+\S+[[:space:]]*\n/ # Lines with version string 22 | ].freeze 23 | 24 | attr_reader :path 25 | 26 | def initialize(path:) 27 | @path = path 28 | end 29 | 30 | # Fetch release notes for the given tag or version number. 31 | # 32 | # E.g. 33 | # fetch("v1.0.1") # => "\nRelease notes for 1.0.1.\n" 34 | # fetch("1.0.1") # => "\nRelease notes for 1.0.1.\n" 35 | # fetch("blergh") # => Chandler::NoMatchingVersion 36 | # 37 | def fetch(tag) 38 | versions.fetch(tag.version_number) do 39 | raise NoMatchingVersion, "Couldn’t find #{tag} in #{path}" 40 | end 41 | end 42 | 43 | def basename 44 | File.basename(path.to_s) 45 | end 46 | 47 | private 48 | 49 | # Transforms the changelog into a hash where the keys are version numbers 50 | # and the values are the release notes for those versions. The values are 51 | # *not* stripped of whitespace. 52 | # 53 | # The version numbers are assumed to be contained at Markdown or Rdoc 54 | # headings. The release notes for those version numbers are the text 55 | # delimited by those headings. The algorithm tries various styles of these 56 | # Markdown and Rdoc headings (see `HEADING_PATTERNS`). 57 | # 58 | # The resulting hash entries look like: 59 | # { "1.0.1" => "\nRelease notes for 1.0.1.\n" } 60 | # 61 | def versions 62 | @versions ||= begin 63 | HEADING_PATTERNS.reduce({}) do |found, heading_re| 64 | versions_at_headings(heading_re).merge(found) 65 | end 66 | end 67 | end 68 | 69 | # rubocop:disable Style/SymbolProc 70 | def versions_at_headings(heading_re) 71 | sections(heading_re).each_with_object({}) do |(heading, text), versions| 72 | tokens = heading.gsub(/[\[\]\(\)`]/, " ").split(/[[:space:]]/) 73 | tokens = tokens.map(&:strip) 74 | version = tokens.find { |t| t.version? } 75 | text_with_references = [text, link_references].join("\n\n") 76 | versions[version.version_number] = text_with_references if version 77 | end 78 | end 79 | # rubocop:enable Style/SymbolProc 80 | 81 | def link_references 82 | @link_references ||= text.split("\n") 83 | .select { |line| line =~ /^\[.*\]: http.*/ } 84 | .join("\n") 85 | end 86 | 87 | # Parses the changelog into a hash, where the keys of the hash are the 88 | # Markdown/rdoc headings matching the specified heading regexp, and values 89 | # are the content delimited by those headings. 90 | # 91 | # E.g. 92 | # { "## v1.0.1\n" => "\nRelease notes for 1.0.1.\n" } 93 | # 94 | def sections(heading_re) 95 | hash = {} 96 | heading = "" 97 | remainder = text 98 | 99 | until remainder.empty? 100 | hash[heading], heading, remainder = remainder.partition(heading_re) 101 | end 102 | 103 | hash 104 | end 105 | 106 | def text 107 | @text ||= IO.read(path, :encoding => "UTF-8") 108 | end 109 | end 110 | end 111 | -------------------------------------------------------------------------------- /test/fixtures/changelog/capistrano-fiftyfive.md: -------------------------------------------------------------------------------- 1 | ## Next release 2 | 3 | * Your contribution here! 4 | 5 | ## 0.20.1 (2015-05-29) 6 | 7 | * An internal change in Capistrano 3.4.0 caused `fiftyfive:aptitude:install` to fail to install packages. This is now fixed. 8 | 9 | ## 0.20.0 (2015-05-29) 10 | 11 | * Increase SSL/TLS security of the generated nginx configuration by following the suggestions of [weakdh.org](https://weakdh.org/sysadmin.html). 12 | 13 | ## 0.19.0 (2015-04-10) 14 | 15 | * Add `--retry=3` to bundle install options. This will help prevent deployment failures in case that a gem initially fails to download during the `bundle install` step. 16 | * Ensure that `--dry-run` works without crashing. This involved working around Capistrano's `download!` behavior (it returns a String normally, but an entirely different object during a dry run). 17 | 18 | ## 0.18.0 19 | 20 | * **The abbreviated log formatter has been removed and is now available in a new gem: `airbrussh`.** With this change, capistrano-fiftyfive no longer automatically changes the logging format of capistrano. To opt into the prettier, more concise format, add the airbrussh gem to your project as explained in the [airbrussh README](https://github.com/mattbrictson/airbrussh#readme). 21 | * The version initializer that capistrano-fiftyfive adds during deployment sets a new value: `Rails.application.config.version_time`. You can use this value within your app for the date and time of the last commit that produced the version that is currently deployed. 22 | 23 | 24 | ## 0.17.2 25 | 26 | * Default self-signed SSL certificate is now more generic (for real this time). 27 | 28 | ## 0.17.1 29 | 30 | * Cosmetic changes to the gemspec. 31 | 32 | ## 0.17.0 33 | 34 | * Write a banner message into `capistrano.log` at the start of each cap run, to aid in troubleshooting. 35 | * Default self-signed SSL certificate is now more generic. 36 | 37 | ## 0.16.0 38 | 39 | * capistrano-fiftyfive now requires capistrano >= 3.3.5 and sshkit => 1.6.1 40 | * `ask_secretly` has been removed in favor of Capistrano's built-in `ask ..., :echo => false` 41 | * `agree` no longer takes an optional second argument 42 | * highline dependency removed 43 | * Install libffi-dev so that Ruby 2.2.0 can be compiled 44 | 45 | ## 0.15.2 46 | 47 | * The capistrano-fiftyfive GitHub repository has changed: it is now . 48 | 49 | ## 0.15.1 50 | 51 | * Remove `-j4` bundler flag 52 | 53 | ## 0.15.0 54 | 55 | * Dump useful troubleshooting information when a deploy fails. 56 | * Nginx/unicorn: fix syntax errors introduced by changes in 0.14.0, ensuring that gzip and far-future expires headers are sent as expected. 57 | 58 | ## 0.14.0 59 | 60 | * The `highline` gem is now a dependency ([#3](https://github.com/mattbrictson/capistrano-fiftyfive/pull/3) from [@ahmozkya](https://github.com/ahmozkya)). 61 | * Dotenv: only mask input when prompting for keys containing the words "key", "secret", "token", or "password". Input for other keys is echoed for easier data entry. 62 | * Dotenv: update `.env` files in sequence rather than in parallel, to avoid parallel command output clobbering the input prompt. 63 | * Nginx/unicorn: tweak reverse-proxy cache settings to prevent cache stampede. 64 | * Nginx/unicorn: apply far-future expires cache headers only for assets that have fingerprints. 65 | 66 | ## 0.13.0 67 | 68 | The provisioning tasks now work for a non-root user that has password-less sudo privileges. Assuming a user named `matt` that can sudo without being prompted for a password ([instructions here](http://askubuntu.com/questions/192050/how-to-run-sudo-command-with-no-password)), simply modify `deploy.rb` with: 69 | 70 | ```ruby 71 | set :fiftyfive_privileged_user, "matt" 72 | ``` 73 | 74 | Now all provisioning tasks that would normally run as root will instead run as `matt` using `sudo`. 75 | 76 | ## 0.12.0 77 | 78 | * capistrano-fiftyfive's abbreviated format now honors the new `SSHKIT_COLOR` environment variable. Set `SSHKIT_COLOR=1` to force ANSI color even on non-ttys (e.g. Jenkins). 79 | * The generated nginx config now enables reverse proxy caching by default. 80 | * INFO messages printed by sshkit are now printed to console under the appropriate rake task heading. 81 | 82 | ## 0.11.1 83 | 84 | Fixes errors caused by PostgreSQL password containing shell-unsafe characters. Passwords are now safely hashed with MD5 before being used in the `CREATE USER` command. 85 | 86 | ## 0.11.0 87 | 88 | * INFO log messages are now included in abbreviated output (e.g. upload/download progress). 89 | * Add `agree()` method to the DSL, which delegates to `HighLine.new.agree`. 90 | * Add `fiftyfive:postgresql:dump`/`restore` tasks. 91 | 92 | ## 0.10.0 93 | 94 | Add support for Ubuntu 14.04 LTS. To provision a 14.04 server, use the new `provision:14_04` task. 95 | 96 | ## 0.9.1 97 | 98 | Flush console output after each line is printed. This allows deployment progress to be monitored in e.g. Jenkins. 99 | 100 | ## 0.9.0 101 | 102 | Initial Rubygems release! 103 | -------------------------------------------------------------------------------- /test/fixtures/changelog/async.md: -------------------------------------------------------------------------------- 1 | # v1.5.2 2 | - Allow using `"consructor"` as an argument in `memoize` (#998) 3 | - Give a better error messsage when `auto` dependency checking fails (#994) 4 | - Various doc updates (#936, #956, #979, #1002) 5 | 6 | # v1.5.1 7 | - Fix issue with `pause` in `queue` with concurrency enabled (#946) 8 | - `while` and `until` now pass the final result to callback (#963) 9 | - `auto` will properly handle concurrency when there is no callback (#966) 10 | - `auto` will now properly stop execution when an error occurs (#988, #993) 11 | - Various doc fixes (#971, #980) 12 | 13 | # v1.5.0 14 | 15 | - Added `transform`, analogous to [`_.transform`](http://lodash.com/docs#transform) (#892) 16 | - `map` now returns an object when an object is passed in, rather than array with non-numeric keys. `map` will begin always returning an array with numeric indexes in the next major release. (#873) 17 | - `auto` now accepts an optional `concurrency` argument to limit the number of running tasks (#637) 18 | - Added `queue#workersList()`, to retrieve the list of currently running tasks. (#891) 19 | - Various code simplifications (#896, #904) 20 | - Various doc fixes :scroll: (#890, #894, #903, #905, #912) 21 | 22 | # v1.4.2 23 | 24 | - Ensure coverage files don't get published on npm (#879) 25 | 26 | # v1.4.1 27 | 28 | - Add in overlooked `detectLimit` method (#866) 29 | - Removed unnecessary files from npm releases (#861) 30 | - Removed usage of a reserved word to prevent :boom: in older environments (#870) 31 | 32 | # v1.4.0 33 | 34 | - `asyncify` now supports promises (#840) 35 | - Added `Limit` versions of `filter` and `reject` (#836) 36 | - Add `Limit` versions of `detect`, `some` and `every` (#828, #829) 37 | - `some`, `every` and `detect` now short circuit early (#828, #829) 38 | - Improve detection of the global object (#804), enabling use in WebWorkers 39 | - `whilst` now called with arguments from iterator (#823) 40 | - `during` now gets called with arguments from iterator (#824) 41 | - Code simplifications and optimizations aplenty ([diff](https://github.com/caolan/async/compare/v1.3.0...v1.4.0)) 42 | 43 | 44 | # v1.3.0 45 | 46 | New Features: 47 | - Added `constant` 48 | - Added `asyncify`/`wrapSync` for making sync functions work with callbacks. (#671, #806) 49 | - Added `during` and `doDuring`, which are like `whilst` with an async truth test. (#800) 50 | - `retry` now accepts an `interval` parameter to specify a delay between retries. (#793) 51 | - `async` should work better in Web Workers due to better `root` detection (#804) 52 | - Callbacks are now optional in `whilst`, `doWhilst`, `until`, and `doUntil` (#642) 53 | - Various internal updates (#786, #801, #802, #803) 54 | - Various doc fixes (#790, #794) 55 | 56 | Bug Fixes: 57 | - `cargo` now exposes the `payload` size, and `cargo.payload` can be changed on the fly after the `cargo` is created. (#740, #744, #783) 58 | 59 | 60 | # v1.2.1 61 | 62 | Bug Fix: 63 | 64 | - Small regression with synchronous iterator behavior in `eachSeries` with a 1-element array. Before 1.1.0, `eachSeries`'s callback was called on the same tick, which this patch restores. In 2.0.0, it will be called on the next tick. (#782) 65 | 66 | 67 | # v1.2.0 68 | 69 | New Features: 70 | 71 | - Added `timesLimit` (#743) 72 | - `concurrency` can be changed after initialization in `queue` by setting `q.concurrency`. The new concurrency will be reflected the next time a task is processed. (#747, #772) 73 | 74 | Bug Fixes: 75 | 76 | - Fixed a regression in `each` and family with empty arrays that have additional properties. (#775, #777) 77 | 78 | 79 | # v1.1.1 80 | 81 | Bug Fix: 82 | 83 | - Small regression with synchronous iterator behavior in `eachSeries` with a 1-element array. Before 1.1.0, `eachSeries`'s callback was called on the same tick, which this patch restores. In 2.0.0, it will be called on the next tick. (#782) 84 | 85 | 86 | # v1.1.0 87 | 88 | New Features: 89 | 90 | - `cargo` now supports all of the same methods and event callbacks as `queue`. 91 | - Added `ensureAsync` - A wrapper that ensures an async function calls its callback on a later tick. (#769) 92 | - Optimized `map`, `eachOf`, and `waterfall` families of functions 93 | - Passing a `null` or `undefined` array to `map`, `each`, `parallel` and families will be treated as an empty array (#667). 94 | - The callback is now optional for the composed results of `compose` and `seq`. (#618) 95 | - Reduced file size by 4kb, (minified version by 1kb) 96 | - Added code coverage through `nyc` and `coveralls` (#768) 97 | 98 | Bug Fixes: 99 | 100 | - `forever` will no longer stack overflow with a synchronous iterator (#622) 101 | - `eachLimit` and other limit functions will stop iterating once an error occurs (#754) 102 | - Always pass `null` in callbacks when there is no error (#439) 103 | - Ensure proper conditions when calling `drain()` after pushing an empty data set to a queue (#668) 104 | - `each` and family will properly handle an empty array (#578) 105 | - `eachSeries` and family will finish if the underlying array is modified during execution (#557) 106 | - `queue` will throw if a non-function is passed to `q.push()` (#593) 107 | - Doc fixes (#629, #766) 108 | 109 | 110 | # v1.0.0 111 | 112 | No known breaking changes, we are simply complying with semver from here on out. 113 | 114 | Changes: 115 | 116 | - Start using a changelog! 117 | - Add `forEachOf` for iterating over Objects (or to iterate Arrays with indexes available) (#168 #704 #321) 118 | - Detect deadlocks in `auto` (#663) 119 | - Better support for require.js (#527) 120 | - Throw if queue created with concurrency `0` (#714) 121 | - Fix unneeded iteration in `queue.resume()` (#758) 122 | - Guard against timer mocking overriding `setImmediate` (#609 #611) 123 | - Miscellaneous doc fixes (#542 #596 #615 #628 #631 #690 #729) 124 | - Use single noop function internally (#546) 125 | - Optimize internal `_each`, `_map` and `_keys` functions. 126 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # chandler 2 | 3 | ⚠️ **This project is no longer actively maintained.** I have found myself embracing tools like [release-drafter](https://github.com/apps/release-drafter) to keep release notes updated automatically, rather than relying on a manually edited CHANGELOG.md. 4 | 5 | --- 6 | 7 | **chandler syncs your CHANGELOG entries to GitHub's release notes so you don't have to enter release notes manually.** For Ruby projects, you can even add chandler to your gem's Rakefile to make this an automatic part of your release process! 8 | 9 | ### How does it work? 10 | 11 | chandler scans your git repository for version tags (e.g. `v1.0.2`), parses out the corresponding release notes for those tags from your `CHANGELOG`, and uploads those notes to your project's [GitHub Releases][gh-releases] via the GitHub API. 12 | 13 | By default, chandler makes reasonable assumptions about: 14 | 15 | - the name of your `CHANGELOG` file, 16 | - your project's GitHub repository URL, and 17 | - the naming convention of your Git version tags. 18 | 19 | These can all be overridden with command line options. 20 | 21 | ### Why go through the trouble? 22 | 23 | [GitHub Releases][gh-releases] are a nice UI for browsing the history of your project and downloading snapshots of each version. It is also structured data that can be queried via GitHub's API, making it a available for third-party integrations. For example, [Sibbell][] can automatically send the release notes out to interested parties whenever you publish a new version. 24 | 25 | But as a considerate developer, you also want a plain text `CHANGELOG` that travels with the code, can be edited collaboratively in pull requests, and so on. 26 | 27 | _But that means you need two copies of the same release notes!_ 😵 28 | 29 | **chandler takes the hassle out of maintaining these two separate formats.** 30 | Your `CHANGELOG` is the authoritative source, and GitHub Releases are updated with a simple `chandler` command. 31 | 32 | ## Requirements 33 | 34 | * Ruby 2.3 or higher 35 | * Your project's `CHANGELOG` must be in Markdown, with version numbers in the headings (similar to the format advocated by [keepachangelog.com](http://keepachangelog.com)) 36 | * You must be an _owner_ or _collaborator_ of the GitHub repository to update its Releases 37 | 38 | ## Installation 39 | 40 | ### 1. Install the gem 41 | 42 | ``` 43 | gem install chandler 44 | ``` 45 | 46 | ### 2. Configure credentials 47 | 48 | #### Option 1 - `.netrc` 49 | 50 | In order to access the GitHub API on your behalf, you must provide chandler with your GitHub credentials. 51 | 52 | Do this by creating a `~/.netrc` file with your GitHub username and password, like this: 53 | 54 | ``` 55 | machine api.github.com 56 | login defunkt 57 | password c0d3b4ssssss! 58 | ``` 59 | 60 | #### Option 2 - Set ENV variables 61 | 62 | Alternatively, just expose the ENV variable `CHANDLER_GITHUB_API_TOKEN` in your CI. 63 | 64 | For more security, you can use an OAuth access token in place of your password. [Here's how to generate one][access-token]. Make sure to enable `public_repo` scope for the token. 65 | 66 | 67 | ## Usage 68 | 69 | To push all `CHANGELOG` entries for all tags to GitHub, just run: 70 | 71 | ``` 72 | chandler push 73 | ``` 74 | 75 | chandler will make educated guesses as to what GitHub repository to use, the location of the `CHANGELOG`, and which tags represent releases. 76 | 77 | You can preview what will happen without actually making changes, using `--dry-run`: 78 | 79 | ``` 80 | chandler push --dry-run 81 | ``` 82 | 83 | To upload only a specific tag (`v1.0.2`, for example): 84 | 85 | ``` 86 | chandler push v1.0.2 87 | ``` 88 | 89 | Other command-line options: 90 | 91 | * `--git=/path/to/project/.git` – location of the local git repository (defaults to `.git`) 92 | * `--github=username/repo` – GitHub repository to upload to (if unspecified, chandler will guess based on your git remotes) 93 | * `--changelog=History.md` – location of the CHANGELOG (defaults to `CHANGELOG.md`) 94 | * `--tag-prefix=myapp-` – specify Git version tags are in the format `myapp-1.0.0` instead of `1.0.0` 95 | 96 | ## GitHub Enterprise 97 | 98 | Chandler supports GitHub Enterprise as well as public GitHub repositories. It will make an educated guess as to where your GitHub Enterprise installation is located based on the `origin` git remote. You can also specify your GitHub Enterprise repository using the `--github` option like this: 99 | 100 | ``` 101 | --github=git@github.mycompany.com:organization/project.git 102 | ``` 103 | 104 | Or like this: 105 | 106 | ``` 107 | --github=https://github.mycompany.com/organization/project 108 | ``` 109 | 110 | To authenticate, Chandler relies on your `~/.netrc`, as explained above. GitHub Enterprise users simply need to replace `api.github.com` with the hostname of your GitHub Enterprise installation (`github.mycompany.com` in the example above). 111 | 112 | ## Rakefile integration 113 | 114 | If you maintain a Ruby gem and use Bundler's gem tasks (i.e. `rake release`) to publish your gem, then you can use chandler to update your GitHub release notes automatically. 115 | 116 | ### 1. Update the gemspec 117 | 118 | ```ruby 119 | spec.add_development_dependency "chandler" 120 | ``` 121 | 122 | ### 2. Modify the Rakefile 123 | 124 | ```ruby 125 | require "bundler/gem_tasks" 126 | require "chandler/tasks" 127 | 128 | # Optional: override default chandler configuration 129 | Chandler::Tasks.configure do |config| 130 | config.changelog_path = "History.md" 131 | config.github_repository = "mattbrictson/mygem" 132 | end 133 | 134 | # Add chandler as a prerequisite for `rake release` 135 | task "release:rubygem_push" => "chandler:push" 136 | ``` 137 | 138 | That's it! Now when you run `rake release`, your GitHub Release notes will be updated automatically based on your `CHANGELOG` entries. 139 | 140 | And yes, chandler uses itself to automatically push its own [release notes][release-notes] to GitHub! Check out the [Rakefile](Rakefile). 141 | 142 | [Sibbell]: http://sibbell.com 143 | [access-token]: https://help.github.com/articles/creating-an-access-token-for-command-line-use/ 144 | [release-notes]: https://github.com/mattbrictson/chandler/releases 145 | [gh-releases]: https://help.github.com/articles/about-releases/ 146 | 147 | ## Contributing 148 | 149 | This project is no longer accepting pull requests. 150 | -------------------------------------------------------------------------------- /test/fixtures/changelog/bootstrap-sass.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 3.3.5 4 | 5 | Fix for standalone Compass extension compatibility. [#914](https://github.com/twbs/bootstrap-sass/issues/914) 6 | 7 | Framework version: Bootstrap **v3.3.5** 8 | 9 | ## 3.3.4 10 | 11 | No Sass-specific changes. 12 | 13 | Framework version: Bootstrap **v3.3.4** 14 | 15 | ## 3.3.3 16 | 17 | This is a re-packaged release of 3.3.2.1 (v3.3.2+1). 18 | 19 | Versions are now strictly semver. 20 | The PATCH version may be ahead of the upstream. 21 | 22 | Framework version: Bootstrap **v3.3.2**. 23 | 24 | ## 3.3.2.1 25 | 26 | * Fix glyphicons regression (revert 443d5b49eac84aec1cb2f8ea173554327bfc8c14) 27 | 28 | ## 3.3.2.0 29 | 30 | * Autoprefixer is now required, and `autoprefixer-rails` is now a dependency for the ruby gem. [#824](https://github.com/twbs/bootstrap-sass/issues/824) 31 | * Minimum precision reduced from 10 to 8 [#821](https://github.com/twbs/bootstrap-sass/issues/821) 32 | * Requiring bootstrap JS from npm now works [#812](https://github.com/twbs/bootstrap-sass/issues/812) 33 | * Fix Sass 3.4.x + IE10 compatibility issue [#803](https://github.com/twbs/bootstrap-sass/issues/803) 34 | * Provide minified JS bundle [#777](https://github.com/twbs/bootstrap-sass/issues/777) 35 | * Bower package is now at bootstrap-sass [#813](https://github.com/twbs/bootstrap-sass/issues/813) 36 | 37 | 38 | ## 3.3.1.0 39 | 40 | * Variables override template at templates/project/_bootstrap-variables.sass 41 | * Readme: Bower + Rails configuration 42 | 43 | ## 3.3.0.1 44 | 45 | * Fix loading issue with the ruby gem version 46 | 47 | ## 3.3.0 48 | 49 | * Improve libsass compatibility 50 | * Support using Bower package with Rails 51 | 52 | ## 3.2.0.2 53 | 54 | Main bootstrap file is now a partial (_bootstrap.scss), for compatibility with Compass 1+. 55 | 56 | Fixed a number of bugs. [Issues closed in v3.2.0.2](https://github.com/twbs/bootstrap-sass/issues?q=is%3Aissue+is%3Aclosed+milestone%3Av3.2.0.2). 57 | 58 | ## 3.2.0.1 59 | 60 | Fixed a number of bugs: [Issues closed in v3.2.0.1](https://github.com/twbs/bootstrap-sass/issues?q=is%3Aissue+is%3Aclosed+milestone%3Av3.2.0.1). 61 | 62 | ## 3.2.0.0 63 | 64 | - Assets (Sass, JS, fonts) moved from `vendor/assets` to `assets`. `bootstrap.js` now contains concatenated JS. 65 | - Compass generator now copies JS and fonts, and provides a better default `styles.sass`. 66 | - Compass, Sprockets, and Mincer asset path helpers are now provided in pure Sass: `bootstrap-compass`, `bootstrap-sprockets`, and `bootstrap-mincer`. 67 | Asset path helpers must be imported before `bootstrap`, more in Readme. 68 | - Sprockets / Mincer JS manifest has been moved to `bootstrap-sprockets.js`. 69 | It can be required without adding Bootstrap JS directory to load path, as it now uses relative paths. 70 | - Sprockets: `depend_on_asset` (`glyphicons.scss`) has been changed to `depend_on` to work around an issue with `depend_on_asset`. 71 | [More information](https://github.com/twbs/bootstrap-sass/issues/592#issuecomment-46570286). 72 | 73 | ## 3.1.1.0 74 | 75 | - Updated Bower docs 76 | 77 | ## 3.1.0.2 78 | 79 | - #523: Rails 3.2 compatibility 80 | - Bugfixes from upstream up to 7eb532262fbd1112215b5a547b9285794b5360ab. 81 | 82 | ## 3.1.0.1 83 | 84 | - #518: `scale` mixin Sass compatibility issue 85 | 86 | ## 3.1.0.0 87 | 88 | * compiles with libsass master 89 | 90 | ## 3.0.2.1 91 | 92 | * fix vendor paths for compass 93 | 94 | ## 3.0.0.0 95 | 96 | * Fully automated (lots of string juggling) LESS -> Sass conversion. - *Gleb Mazovetskiy* 97 | * Ported rake task from vwall/compass-twitter-bootstrap to convert Bootstrap upstream - *Peter Gumeson* 98 | * Moved javascripts to us `bootstrap-component.js` to `bootstrap/component.js` - *Peter Gumeson* 99 | 100 | ## 2.3.2.2 101 | 102 | * Allow sass-rails `>= 3.2` - *Thomas McDonald* 103 | 104 | ## 2.3.2.1 105 | 106 | ## 2.3.2.0 107 | 108 | * Update to Bootstrap 2.3.2 - *Dan Allen* 109 | 110 | ## 2.3.1.3 111 | 112 | * Find the correct Sprockets context for the `image_path` function - *Tristan Harward, Gleb Mazovetskiy* 113 | 114 | ## 2.3.1.2 115 | 116 | * Fix changes to image url - *Gleb Mazovetskiy* 117 | * Copy _variables into project on Compass install - *Phil Thompson* 118 | * Add `bootstrap-affix` to the Compass template file - *brief* 119 | 120 | ## 2.3.1.1 (yanked) 121 | 122 | * Change how image_url is handled internally - *Tristan Harward* 123 | * Fix some font variables not having `!default` - *Thomas McDonald* 124 | 125 | ## 2.3.0.0 126 | * [#290] Update to Bootstrap 2.3.0 - *Tristan Harward* 127 | * Fix `rake:debug` with new file locations - *Thomas McDonald* 128 | * Add draft contributing document - *Thomas McDonald* 129 | * [#260] Add our load path to the global Sass load path - *Tristan Harward* 130 | * [#275] Use GitHub notation in Sass head testing gemfile - *Timo Schilling* 131 | * [#279, #283] Readme improvements - *theverything, Philip Arndt* 132 | 133 | ## 2.2.2.0 134 | * [#270] Update to Bootstrap 2.2.2 - *Tristan Harward* 135 | * [#266] Add license to gemspec - *Peter Marsh* 136 | 137 | ## 2.2.1.1 138 | * [#258] Use `bootstrap` prefix for `@import`ing files in `bootstrap/bootstrap.scss` - *Umair Siddique* 139 | 140 | ## 2.2.1.0 141 | * [#246] Update to Bootstrap 2.2.1 - *Tristan Harward* 142 | * [#246] Pull Bootstrap updates from jlong/sass-twitter-bootstrap - *Tristan Harward* 143 | 144 | ## 2.1.1.0 145 | * Update to Bootstrap 2.1.1 146 | * [#222] Remove 100% multiplier in vertical-three-colours 147 | * [#227] Fix IE component animation collapse 148 | * [#228] Fix variables documentation link 149 | * [#231] Made .input-block-level a class as well as mixin 150 | 151 | ## 2.1.0.1 152 | * [#219] Fix expected a color. Got: transparent. 153 | * [#207] Add missing warning style for table row highlighting 154 | * [#208] Use grid-input-span for input spans 155 | 156 | ## 2.1.0.0 157 | * Updated to Bootstrap 2.1 158 | * Changed some mixin names to be more consistent. Nested mixins in Less are separated by a `-` when they are flattened in Sass. 159 | 160 | ## 2.0.4.1 161 | * Fix `.row-fluid > spanX` nesting 162 | * Small Javascript fixes for those staying on the 2.0.4 release 163 | * Add `!default` to z-index variables. 164 | 165 | ## 2.0.4.0 166 | * Updated to Bootstrap 2.0.4 167 | * Switched to Bootstrap 2.0.3+'s method of separating responsive files 168 | * [#149, #150] Fix off by one error introduced with manual revert of media query breakpoints 169 | * `rake debug` and `rake test` both compile bootstrap & bootstrap-responsive 170 | 171 | ## 2.0.3.1 172 | * [#145, #146] Fix button alignment in collapsing navbar as a result of an incorrect variable 173 | 174 | ## 2.0.3 175 | * Updated to Bootstrap 2.0.3 176 | * [#106] Support for Rails < 3.1 through Compass 177 | * [#132] Add CI testing 178 | * [#106] Support Rails w/Compass 179 | * [#134] Fix support for Rails w/Compass 180 | 181 | ## 2.0.2 182 | * [#86] Updated to Bootstrap 2.0.2 183 | Things of note: static navbars now have full width. (to be fixed in 2.0.3) `.navbar-inner > .container { width:940px; }` seems to work in the meanwhile 184 | * [#62] Fixed asset compilation taking a *very* long time. 185 | * [#69, #79, #80] \(Hopefully) clarified README. Now with less cat humour. 186 | * [#91] Removed doubled up Sass extensions for Rails. 187 | * [#63, #73] Allow for overriding of image-path 188 | * [[SO](http://stackoverflow.com/a/9909626/241212)] Added makeFluidColumn mixin for defining fluid columns. Fluid rows must use `@extend .row-fluid`, and any column inside it can use `@include makeFluidColumn(num)`, where `num` is the number of columns. Unfortunately, there is a rather major limitation to this: margins on first-child elements must be overriden. See the attached Stack Overflow answer for more information. 189 | 190 | ## 2.0.1 191 | * Updated to Bootstrap 2.0.1 192 | * Modified `@mixin opacity()` to take an argument `0...1` rather than `0...100` to be consistent with Compass. 193 | 194 | ## 2.0.0 195 | * Updated to Bootstrap 2.0.0 196 | -------------------------------------------------------------------------------- /test/chandler/changelog_test.rb: -------------------------------------------------------------------------------- 1 | require "minitest_helper" 2 | require "chandler/changelog" 3 | 4 | class Chandler::ChangelogTest < Minitest::Test 5 | def test_fetch_raises_for_nonexistent_version 6 | changelog = new_changelog("airbrussh.md") 7 | assert_raises(Chandler::Changelog::NoMatchingVersion) do 8 | changelog.fetch("v0.99.0") 9 | end 10 | end 11 | 12 | def test_fetch_activeadmin_versions 13 | changelog = new_changelog("activeadmin.md") 14 | 15 | assert_match("only once. [#5377] by [@kjeldahl]", changelog.fetch("v1.4.2")) 16 | assert_match( 17 | "[#5377]: https://github.com/activeadmin/activeadmin/pull/5377", 18 | changelog.fetch("v1.4.2") 19 | ) 20 | assert_match( 21 | "[@kjeldahl]: https://github.com/kjeldahl", 22 | changelog.fetch("v1.4.2") 23 | ) 24 | 25 | assert_match("delete. [#5583] by [@tiagotex]", changelog.fetch("v1.4.1")) 26 | assert_match( 27 | "[#5583]: https://github.com/activeadmin/activeadmin/pull/5583", 28 | changelog.fetch("v1.4.1") 29 | ) 30 | assert_match( 31 | "[@tiagotex]: https://github.com/tiagotex", 32 | changelog.fetch("v1.4.1") 33 | ) 34 | end 35 | 36 | def test_fetch_actionview_versions 37 | changelog = new_changelog("actionview.md") 38 | 39 | assert_match("`translate` should handle `rai", changelog.fetch("v4.1.12")) 40 | assert_match("No changes.", changelog.fetch("v4.1.11")) 41 | assert_match("Local variable in a partial is", changelog.fetch("v4.1.10")) 42 | assert_match("Added an explicit error message", changelog.fetch("v4.1.9")) 43 | assert_match("Update `select_tag` to work", changelog.fetch("v4.1.8")) 44 | end 45 | 46 | def test_fetch_airbrussh_versions 47 | changelog = new_changelog("airbrussh.md") 48 | 49 | assert_match( 50 | "Fix `Marshal.dump` warnings by removing `deep_copy` workaround "\ 51 | "that it is no longer needed for the latest SSHKit "\ 52 | "([#10](https://github.com/mattbrictson/airbrussh/issues/10)).", 53 | changelog.fetch("v0.4.1") 54 | ) 55 | assert_match("Changes to ensure compatibility", changelog.fetch("v0.4.0")) 56 | assert_match("Explicitly specify UTF-8", changelog.fetch("v0.4.0")) 57 | assert_match("New `config.banner` option", changelog.fetch("v0.3.0")) 58 | assert_match("New `config.command_output`", changelog.fetch("v0.3.0")) 59 | assert_match("Un-pin SSHKit dependency", changelog.fetch("v0.2.1")) 60 | assert_match("Pin SSHKit dependency at", changelog.fetch("v0.2.0")) 61 | assert_match("Initial release", changelog.fetch("v0.0.1")) 62 | end 63 | 64 | def test_fetch_angular_versions 65 | changelog = new_changelog("angular.md") 66 | 67 | assert_match("Copy `inputs` for expressions", changelog.fetch("1.5.0")) 68 | assert_match("does not affect the `ngSwipe`", changelog.fetch("1.5.0-rc.2")) 69 | assert_match("**filterFilter:** due to", changelog.fetch("1.4.0-beta.2")) 70 | end 71 | 72 | def test_fetch_async_versions 73 | changelog = new_changelog("async.md") 74 | 75 | assert_match('Allow using `"consructor"`', changelog.fetch("v1.5.2")) 76 | assert_match("Various doc fixes (#971, #980)", changelog.fetch("v1.5.1")) 77 | assert_match("Added `asyncify`/`wrapSync`", changelog.fetch("v1.3.0")) 78 | assert_match("No known breaking changes", changelog.fetch("v1.0.0")) 79 | end 80 | 81 | def test_fetch_bootstrap_sass_versions 82 | changelog = new_changelog("bootstrap-sass.md") 83 | 84 | assert_match("Fix for standalone Compass", changelog.fetch("v3.3.5")) 85 | assert_match("No Sass-specific changes.", changelog.fetch("v3.3.4")) 86 | assert_match("This is a re-packaged release", changelog.fetch("v3.3.3")) 87 | assert_match("Fix glyphicons regression", changelog.fetch("v3.3.2.1")) 88 | assert_match("Autoprefixer is now required", changelog.fetch("v3.3.2.0")) 89 | end 90 | 91 | def test_fetch_bundler_versions 92 | changelog = new_changelog("bundler.md") 93 | 94 | assert_match("don't add BUNDLED WITH to the", changelog.fetch("v1.10.4")) 95 | assert_match("allow missing gemspec files", changelog.fetch("v1.10.3")) 96 | assert_match("fix regression in `bundle update", changelog.fetch("v1.10.2")) 97 | assert_match("silence ruby warning when", changelog.fetch("v1.10.1")) 98 | assert_match("(this space intentionally left", changelog.fetch("v1.10.0")) 99 | end 100 | 101 | def test_fetch_capistrano_fiftyfive_versions 102 | changelog = new_changelog("capistrano-fiftyfive.md") 103 | 104 | assert_match("An internal change in Capistrano", changelog.fetch("v0.20.1")) 105 | assert_match("Increase SSL/TLS security", changelog.fetch("v0.20.0")) 106 | assert_match("Add `--retry=3` to bundle", changelog.fetch("v0.19.0")) 107 | assert_match("The abbreviated log formatter", changelog.fetch("v0.18.0")) 108 | assert_match("Default self-signed SSL", changelog.fetch("v0.17.2")) 109 | end 110 | 111 | def test_fetch_capistrano_versions 112 | changelog = new_changelog("capistrano.md") 113 | 114 | assert_match("Fixed fetch revision", changelog.fetch("v3.4.0")) 115 | assert_match("Fixed setting properties twice", changelog.fetch("v3.3.5")) 116 | assert_match("Rely on a newer version of", changelog.fetch("v3.3.4")) 117 | assert_match("Added the variable `:repo_tree`", changelog.fetch("v3.3.3")) 118 | assert_match("3.2.0 introduced some behaviour", changelog.fetch("v3.2.1")) 119 | end 120 | 121 | def test_fetch_carrierwave_versions 122 | changelog = new_changelog("carrierwave.md") 123 | 124 | assert_match("Memoize uploaders and", changelog.fetch("v0.10.0")) 125 | assert_match("Use integer time (UTC)", changelog.fetch("v0.9.0")) 126 | assert_match("Remove 'fog\\_endpoint' in favor", changelog.fetch("v0.8.0")) 127 | assert_match("add a override to allow fog", changelog.fetch("v0.7.1")) 128 | assert_match("Rename 'fog\\_host' config option", changelog.fetch("v0.7.0")) 129 | end 130 | 131 | def test_fetch_devise_versions 132 | changelog = new_changelog("devise.md") 133 | 134 | assert_match("Clean up reset password token", changelog.fetch("v3.5.1")) 135 | assert_match("Devise default views now have", changelog.fetch("v3.4.1")) 136 | assert_match("Support added for Rails 4.2", changelog.fetch("v3.4.0")) 137 | assert_match("Support multiple warden config", changelog.fetch("v3.3.0")) 138 | assert_match("`bcrypt` dependency updated", changelog.fetch("v3.2.4")) 139 | end 140 | 141 | def test_fetch_less_js_versions 142 | changelog = new_changelog("less.js.md") 143 | 144 | assert_match("Underscore now allowed in dimen", changelog.fetch("2.6.0")) 145 | assert_match("Fix import inline a URL", changelog.fetch("2.5.3")) 146 | assert_match("less.parse now exposes a way to", changelog.fetch("2.2.0")) 147 | assert_match("browser bundle no longer leaks", changelog.fetch("2.0.0-b3")) 148 | assert_match("support @import-once", changelog.fetch("1.3.1")) 149 | end 150 | 151 | def test_fetch_rake_versions 152 | changelog = new_changelog("rake.rdoc") 153 | 154 | assert_match("Rake no longer edits ARGV", changelog.fetch("v10.4.2")) 155 | assert_match("Reverted fix for #277 as it", changelog.fetch("v10.4.1")) 156 | assert_match("Upgraded to minitest 5.", changelog.fetch("v10.4.0")) 157 | assert_match("Rake no longer infinitely loops", changelog.fetch("v10.3.2")) 158 | assert_match("Added --build-all option to rake", changelog.fetch("v10.3")) 159 | end 160 | 161 | def test_fetch_realm_cocoa 162 | changelog = new_changelog("realm-cocoa.md") 163 | 164 | assert_match("Fix a crash when opening a Realm", changelog.fetch("v0.98.5")) 165 | assert_match("addOrUpdate:/createOrUpdate: to", changelog.fetch("v0.98.4")) 166 | assert_match("Fix crashes when deleting an obj", changelog.fetch("v0.98.1")) 167 | assert_match("Added anonymous analytics on", changelog.fetch("v0.94.0")) 168 | assert_match("RLMArray has been split into", changelog.fetch("v0.87.0")) 169 | end 170 | 171 | def test_fetch_rst_definitions_semver 172 | changelog = new_changelog("rst-definition.md") 173 | 174 | assert_match("Added ACME project", changelog.fetch("0.0.1")) 175 | assert_match("Pre-release", changelog.fetch("0.0.2-rc1")) 176 | assert_match("Dev pre-release", changelog.fetch("0.0.2-dev-xyz")) 177 | assert_match("Release", changelog.fetch("0.0.2")) 178 | assert_match("Release 0.1", changelog.fetch("0.1.0")) 179 | assert_match("Update", changelog.fetch("v0.1.1")) 180 | end 181 | 182 | def test_fetch_rubocop_versions 183 | changelog = new_changelog("rubocop.md") 184 | 185 | assert_match("Adjust behavior of `Trailing", changelog.fetch("v0.32.0")) 186 | assert_match("`Rails/TimeZone` emits", changelog.fetch("v0.31.0")) 187 | assert_match("For assignments with line break", changelog.fetch("v0.30.1")) 188 | assert_match("Do not register offenses on", changelog.fetch("v0.30.0")) 189 | assert_match("Use Parser functionality rather", changelog.fetch("v0.29.1")) 190 | end 191 | 192 | def test_fetch_sshkit_versions 193 | changelog = new_changelog("sshkit.md") 194 | 195 | assert_match("Fix a regression in 1.7.0", changelog.fetch("v1.7.1")) 196 | assert_match("Update Vagrantfile to use", changelog.fetch("v1.7.0")) 197 | end 198 | 199 | def test_fetch_twitter_versions 200 | changelog = new_changelog("twitter.md") 201 | 202 | assert_match("Add `Twitter::NullObject", changelog.fetch("v5.14.0")) 203 | assert_match("Deprecate `Twitter::REST::Client", changelog.fetch("v5.13.0")) 204 | assert_match("Rescue `Twitter::Error::NotFound", changelog.fetch("v5.12.0")) 205 | assert_match("Return a Twitter::NullObject", changelog.fetch("v5.11.0")) 206 | assert_match("Add support for extended ent", changelog.fetch("v5.10.0")) 207 | end 208 | 209 | private 210 | 211 | def new_changelog(fixture) 212 | path = File.expand_path("../../fixtures/changelog/#{fixture}", __FILE__) 213 | Chandler::Changelog.new(:path => path) 214 | end 215 | end 216 | -------------------------------------------------------------------------------- /test/fixtures/changelog/actionview.md: -------------------------------------------------------------------------------- 1 | ## Rails 4.1.12 (June 22, 2015) ## 2 | 3 | * `translate` should handle `raise` flag correctly in case of both main and default 4 | translation is missing. 5 | 6 | Fixes #19967 7 | 8 | *Bernard Potocki* 9 | 10 | * `translate` should accept nils as members of the `:default` 11 | parameter without raising a translation missing error. Fixes a 12 | regression introduced 362557e. 13 | 14 | Fixes #19419 15 | 16 | *Justin Coyne* 17 | 18 | * `number_to_percentage` does not crash with `Float::NAN` or `Float::INFINITY` 19 | as input when `precision: 0` is used. 20 | 21 | Fixes #19227. 22 | 23 | *Yves Senn* 24 | 25 | 26 | ## Rails 4.1.11 (June 16, 2015) ## 27 | 28 | * No changes. 29 | 30 | 31 | ## Rails 4.1.10 (March 19, 2015) ## 32 | 33 | * Local variable in a partial is now available even if a falsy value is 34 | passed to `:object` when rendering a partial. 35 | 36 | Fixes #17373. 37 | 38 | *Agis Anastasopoulos* 39 | 40 | * Default translations that have a lower precidence than an html safe default, 41 | but are not themselves safe, should not be marked as html_safe. 42 | 43 | *Justin Coyne* 44 | 45 | ## Rails 4.1.9 (January 6, 2015) ## 46 | 47 | * Added an explicit error message, in `ActionView::PartialRenderer` 48 | for partial `rendering`, when the value of option `as` has invalid characters. 49 | 50 | *Angelo Capilleri* 51 | 52 | 53 | ## Rails 4.1.8 (November 16, 2014) ## 54 | 55 | * Update `select_tag` to work correctly with `:include_blank` option passing a string. 56 | 57 | Fixes #16483. 58 | 59 | *Frank Groeneveld* 60 | 61 | 62 | ## Rails 4.1.7.1 (November 19, 2014) ## 63 | 64 | * No changes. 65 | 66 | 67 | ## Rails 4.1.7 (October 29, 2014) ## 68 | 69 | * No changes. 70 | 71 | 72 | ## Rails 4.1.6 (September 11, 2014) ## 73 | 74 | * Fix that render layout: 'messages/layout' should also be added to the dependency tracker tree. 75 | 76 | *DHH* 77 | 78 | * Return an absolute instead of relative path from an asset url in the case 79 | of the `asset_host` proc returning nil 80 | 81 | *Jolyon Pawlyn* 82 | 83 | * Fix `html_escape_once` to properly handle hex escape sequences (e.g. ᨫ) 84 | 85 | *John F. Douthat* 86 | 87 | * Bring `cache_digest` rake tasks up-to-date with the latest API changes 88 | 89 | *Jiri Pospisil* 90 | 91 | 92 | ## Rails 4.1.5 (August 18, 2014) ## 93 | 94 | * No changes. 95 | 96 | 97 | ## Rails 4.1.4 (July 2, 2014) ## 98 | 99 | * No changes. 100 | 101 | 102 | ## Rails 4.1.3 (July 2, 2014) ## 103 | 104 | * No changes. 105 | 106 | 107 | ## Rails 4.1.2 (June 26, 2014) ## 108 | 109 | * Change `asset_path` to use File.join to create proper paths. 110 | 111 | https://some.host.com//assets/some.js 112 | 113 | becomes 114 | 115 | https://some.host.com/assets/some.js 116 | 117 | *Peter Schröder* 118 | 119 | * `collection_check_boxes` respects `:index` option for the hidden field name. 120 | 121 | Fixes #14147. 122 | 123 | *Vasiliy Ermolovich* 124 | 125 | * `date_select` helper with option `with_css_classes: true` does not overwrite other classes. 126 | 127 | *Izumi Wong-Horiuchi* 128 | 129 | 130 | ## Rails 4.1.1 (May 6, 2014) ## 131 | 132 | * No changes. 133 | 134 | 135 | ## Rails 4.1.0 (April 8, 2014) ## 136 | 137 | * Fixed ActionView::Digestor template lookup to use the lookup_context exclusively, and not rely on the passed-in format. 138 | This unfortunately means that the cache_key changed, so upgrading will invalidate all prior caches. Take note if you rely 139 | heavily on caching in production when you push this live. 140 | 141 | *DHH* 142 | 143 | * `number_to_percentage` does not crash with `Float::NAN` or `Float::INFINITY` 144 | as input. 145 | 146 | Fixes #14405. 147 | 148 | *Yves Senn* 149 | 150 | * Take variants into account when calculating template digests in ActionView::Digestor. 151 | 152 | The arguments to ActionView::Digestor#digest are now being passed as a hash 153 | to support variants and allow more flexibility in the future. The support for 154 | regular (required) arguments is deprecated and will be removed in Rails 5.0 or later. 155 | 156 | *Piotr Chmolowski, Łukasz Strzałkowski* 157 | 158 | * Fix a problem where the default options for the `button_tag` helper were not 159 | being applied correctly. 160 | 161 | Fixes #14255. 162 | 163 | *Sergey Prikhodko* 164 | 165 | * Fix ActionView label translation for more than 10 nested elements. 166 | 167 | *Vladimir Krylov* 168 | 169 | * Added `:plain`, `:html` and `:body` options for `render` method. Please see 170 | the ActionPack release notes for more detail. 171 | 172 | *Prem Sichanugrist* 173 | 174 | * Date select helpers accept a format string for the months selector via the 175 | new option `:month_format_string`. 176 | 177 | When rendered, the format string gets passed keys `:number` (integer), and 178 | `:name` (string), in order to be able to interpolate them as in 179 | 180 | '%{name} (%02d)' 181 | 182 | for example. 183 | 184 | This option is motivated by #13618. 185 | 186 | *Xavier Noria* 187 | 188 | * Added `config.action_view.raise_on_missing_translations` to define whether an 189 | error should be raised for missing translations. 190 | 191 | Fixes #13196. 192 | 193 | *Kassio Borges* 194 | 195 | * Improved ERB dependency detection. New argument types and formattings for the `render` 196 | calls can be matched. 197 | 198 | Fixes #13074, #13116. 199 | 200 | *João Britto* 201 | 202 | * Use `display:none` instead of `display:inline` for hidden fields. 203 | 204 | Fixes #6403. 205 | 206 | *Gaelian Ditchburn* 207 | 208 | * The `video_tag` helper now accepts a number for `:size`. 209 | 210 | The `:size` option of the `video_tag` helper now can be specified 211 | with a stringified number. The `width` and `height` attributes of 212 | the generated tag will be the same. 213 | 214 | *Kuldeep Aggarwal* 215 | 216 | * Escape format, negative_format and units options of number helpers 217 | 218 | Fixes: CVE-2014-0081 219 | 220 | * A Cycle object should accept an array and cycle through it as it would with a set of 221 | comma-separated objects. 222 | 223 | arr = [1,2,3] 224 | cycle(arr) # => '1' 225 | cycle(arr) # => '2' 226 | cycle(arr) # => '3' 227 | 228 | Previously, it would return the array as a string, because it took the array as a 229 | single object: 230 | 231 | arr = [1,2,3] 232 | cycle(arr) # => '[1,2,3]' 233 | cycle(arr) # => '[1,2,3]' 234 | cycle(arr) # => '[1,2,3]' 235 | 236 | *Kristian Freeman* 237 | 238 | * Label tags generated by collection helpers only inherit the `:index` and 239 | `:namespace` from the input, because only these attributes modify the 240 | `for` attribute of the label. Also, the input attributes don't have 241 | precedence over the label attributes anymore. 242 | 243 | Before: 244 | 245 | collection = [[1, true, { class: 'foo' }]] 246 | f.collection_check_boxes :options, collection, :second, :first do |b| 247 | b.label(class: 'my_custom_class') 248 | end 249 | 250 | # => 251 | 252 | After: 253 | 254 | collection = [[1, true, { class: 'foo' }]] 255 | f.collection_check_boxes :options, collection, :second, :first do |b| 256 | b.label(class: 'my_custom_class') 257 | end 258 | 259 | # => 260 | 261 | *Andriel Nuernberg* 262 | 263 | * Fix a long-standing bug in `json_escape` that caused quotation marks to be stripped. 264 | This method also escapes the \u2028 and \u2029 unicode newline characters which are 265 | treated as \n in JavaScript. This matches the behaviour of the AS::JSON encoder. (The 266 | original change in the encoder was introduced in #10534.) 267 | 268 | *Godfrey Chan* 269 | 270 | * `ActionView::MissingTemplate` includes underscore when raised for a partial. 271 | 272 | Fixes #13002. 273 | 274 | *Yves Senn* 275 | 276 | * Use `set_backtrace` instead of instance variable `@backtrace` in ActionView exceptions. 277 | 278 | *Shimpei Makimoto* 279 | 280 | * Fix `simple_format` escapes own output when passing `sanitize: true`. 281 | 282 | *Paul Seidemann* 283 | 284 | * Ensure `ActionView::Digestor.cache` is correctly cleaned up when 285 | combining recursive templates with `ActionView::Resolver.caching = false`. 286 | 287 | *wyaeld* 288 | 289 | * Fix `collection_check_boxes` so the generated hidden input correctly uses the 290 | name attribute provided in the options hash. 291 | 292 | *Angel N. Sciortino* 293 | 294 | * Fix some edge cases for the AV `select` helper with the `:selected` option. 295 | 296 | *Bogdan Gusiev* 297 | 298 | * Enable passing a block to the `select` helper. 299 | 300 | Example: 301 | 302 | <%= select(report, "campaign_ids") do %> 303 | <% available_campaigns.each do |c| -%> 304 | <%= content_tag(:option, c.name, value: c.id, data: { tags: c.tags.to_json }) %> 305 | <% end -%> 306 | <% end -%> 307 | 308 | *Bogdan Gusiev* 309 | 310 | * Handle `:namespace` form option in collection labels. 311 | 312 | *Vasiliy Ermolovich* 313 | 314 | * Fix `form_for` when both `namespace` and `as` options are present. 315 | 316 | The `as` option no longer overwrites the `namespace` option when 317 | generating an HTML id attribute of the form element. 318 | 319 | *Adam Niedzielski* 320 | 321 | * Fix `excerpt` when `:separator` is `nil`. 322 | 323 | *Paul Nikitochkin* 324 | 325 | * Only cache template digests if `config.cache_template_loading` is true. 326 | 327 | *Josh Lauer*, *Justin Ridgewell* 328 | 329 | * Fix a bug where the lookup details were not being taken into account 330 | when caching the digest of a template - changes to the details now 331 | cause a different cache key to be used. 332 | 333 | *Daniel Schierbeck* 334 | 335 | * Added an `extname` hash option to the `javascript_include_tag` method. 336 | 337 | Before: 338 | 339 | javascript_include_tag('templates.jst') 340 | # => 341 | 342 | After: 343 | 344 | javascript_include_tag('templates.jst', extname: false ) 345 | # => 346 | 347 | *Nathan Stitt* 348 | 349 | * Fix `current_page?` when the URL contains escaped characters and the 350 | original URL is using the hexadecimal lowercased. 351 | 352 | *Rafael Mendonça França* 353 | 354 | * Fix `text_area` to behave like `text_field` when `nil` is given as a 355 | value. 356 | 357 | Before: 358 | 359 | f.text_field :field, value: nil #=> 360 | f.text_area :field, value: nil #=> 361 | 362 | After: 363 | 364 | f.text_area :field, value: nil #=> 365 | 366 | *Joel Cogen* 367 | 368 | * Allow `grouped_options_for_select` to optionally contain html attributes 369 | as the last element of the array. 370 | 371 | grouped_options_for_select( 372 | [["North America", [['United States','US'],"Canada"], data: { foo: 'bar' }]] 373 | ) 374 | 375 | *Vasiliy Ermolovich* 376 | 377 | * Fix default rendered format problem when calling `render` without :content_type option. 378 | It should return :html. Fix #11393. 379 | 380 | *Gleb Mazovetskiy*, *Oleg*, *kennyj* 381 | 382 | * Fix `link_to` with block and url hashes. 383 | 384 | Before: 385 | 386 | link_to(action: 'bar', controller: 'foo') { content_tag(:span, 'Example site') } 387 | # => "Example site" 388 | 389 | After: 390 | 391 | link_to(action: 'bar', controller: 'foo') { content_tag(:span, 'Example site') } 392 | # => "Example site" 393 | 394 | *Murahashi Sanemat Kenichi* 395 | 396 | * Fix "Stack Level Too Deep" error when rendering recursive partials. 397 | 398 | Fixes #11340. 399 | 400 | *Rafael Mendonça França* 401 | 402 | * Added an `enforce_utf8` hash option for `form_tag` method. 403 | 404 | Control to output a hidden input tag with name `utf8` without monkey 405 | patching. 406 | 407 | Before: 408 | 409 | form_tag 410 | # => '
....
' 411 | 412 | After: 413 | 414 | form_tag 415 | # => '
....
' 416 | 417 | form_tag({}, { :enforce_utf8 => false }) 418 | # => '
....
' 419 | 420 | *ma2gedev* 421 | 422 | * Remove the deprecated `include_seconds` argument from `distance_of_time_in_words`, 423 | pass in an `:include_seconds` hash option to use this feature. 424 | 425 | *Carlos Antonio da Silva* 426 | 427 | * Remove deprecated block passing to `FormBuilder#new`. 428 | 429 | *Vipul A M* 430 | 431 | * Pick `DateField` `DateTimeField` and `ColorField` values from stringified options 432 | allowing use of symbol keys with helpers. 433 | 434 | *Jon Rowe* 435 | 436 | * Remove the deprecated `prompt` argument from `grouped_options_for_select`, 437 | pass in a `:prompt` hash option to use this feature. 438 | 439 | *kennyj* 440 | 441 | * Always escape the result of `link_to_unless` methods. 442 | 443 | Before: 444 | 445 | link_to_unless(true, 'Showing', 'github.com') 446 | # => "Showing" 447 | 448 | After: 449 | 450 | link_to_unless(true, 'Showing', 'github.com') 451 | # => "<b>Showing</b>" 452 | 453 | *dtaniwaki* 454 | 455 | * Use a case insensitive URI Regexp for #asset_path. 456 | 457 | This fixes a problem where the same asset path using different cases 458 | was generating different URIs. 459 | 460 | Before: 461 | 462 | image_tag("HTTP://google.com") 463 | # => "\"Google\"" 464 | image_tag("http://google.com") 465 | # => "\"Google\"" 466 | 467 | After: 468 | 469 | image_tag("HTTP://google.com") 470 | # => "\"Google\"" 471 | image_tag("http://google.com") 472 | # => "\"Google\"" 473 | 474 | *David Celis* 475 | 476 | * Allow `collection_check_boxes` and `collection_radio_buttons` to 477 | optionally contain html attributes as the last element of the array. 478 | 479 | *Vasiliy Ermolovich* 480 | 481 | * Update the HTML `BOOLEAN_ATTRIBUTES` in `ActionView::Helpers::TagHelper` 482 | to conform to the latest HTML 5.1 spec. Add attributes `allowfullscreen`, 483 | `default`, `inert`, `sortable`, `truespeed`, `typemustmatch`. Fix attribute 484 | `seamless` (previously misspelled `seemless`). 485 | 486 | *Alex Peattie* 487 | 488 | * Fix an issue where partials with a number in the filename were not 489 | being digested for cache dependencies. 490 | 491 | *Bryan Ricker* 492 | 493 | * First release, ActionView extracted from ActionPack. 494 | 495 | *Piotr Sarnacki*, *Łukasz Strzałkowski* 496 | 497 | Please check [4-0-stable (ActionPack's CHANGELOG)](https://github.com/rails/rails/blob/4-0-stable/actionpack/CHANGELOG.md) for previous changes. 498 | -------------------------------------------------------------------------------- /test/fixtures/changelog/capistrano.md: -------------------------------------------------------------------------------- 1 | # Capistrano 3.x Changelog 2 | 3 | Reverse Chronological Order: 4 | 5 | ## master 6 | 7 | https://github.com/capistrano/capistrano/compare/v3.4.0...HEAD 8 | 9 | * Removed the post-install message (@Kriechi) 10 | 11 | * Minor changes 12 | * Fix filtering behaviour when using literal hostnames in on() block (@townsen) 13 | * Added options to set username and password when using Subversion as SCM (@dsthode) 14 | * Allow after() to refer to tasks that have not been loaded yet (@jcoglan) 15 | * Ensure scm fetch_revision methods strip trailing whitespace (@mattbrictson) 16 | * Allow use "all" as string for server filtering (@theist) 17 | 18 | ## `3.4.0` 19 | 20 | https://github.com/capistrano/capistrano/compare/v3.3.5...v3.4.0 21 | 22 | * Fixed fetch revision for annotated git tags. (@igorsokolov) 23 | * Fixed updating roles when custom user or port is specified. (@ayastreb) 24 | * Disables statistics collection. 25 | 26 | * `bin/` is not suggested to be in `linked_dirs` anymore (@kirs) 27 | * bin/ is often checked out into repo 28 | * https://github.com/capistrano/bundler/issues/45#issuecomment-69349237 29 | 30 | * Bugfix: 31 | * release_roles did not honour additional property filtering (@townsen) 32 | * Refactored and simplified property filtering code (@townsen) 33 | 34 | * Breaking Changes 35 | * Hosts with the same name are now consolidated into one irrespective of the 36 | user and port. This allows multiple declarations of a server to be made safely. 37 | The last declared properties will win. See capistranorb.com Properties documentation 38 | for details. 39 | * Inside the on() block the host variable is now a copy of the host, so changes can be 40 | made within the block (such as dynamically overriding the user) that will not persist. 41 | This is very convenient for switching the SSH user temporarily to 'root' for example. 42 | 43 | * Minor changes 44 | * Add role_properties() method (see capistrano.github.io PR for doc) (@townsen) 45 | * Add equality syntax ( eg. port: 1234) for property filtering (@townsen) 46 | * Add documentation regarding property filtering (@townsen) 47 | * Clarify wording and recommendation in stage template. (@Kriechi) 48 | * Both available syntaxes provide similar functionality, do not use both for the same server+role combination. 49 | * Allow specification of repo_path using stage variable 50 | default is as before (@townsen) 51 | 52 | ## `3.3.5` 53 | 54 | https://github.com/capistrano/capistrano/compare/v3.3.4...v3.3.5 55 | 56 | * Fixed setting properties twice when creating new server. See [issue 57 | #1214](https://github.com/capistrano/capistrano/issues/1214) (@ayastreb) 58 | 59 | ## `3.3.4` 60 | 61 | https://github.com/capistrano/capistrano/compare/v3.3.3...v3.3.4 62 | 63 | * Minor changes: 64 | * Rely on a newer version of capistrano-stats with better privacy (@leehambley) 65 | * Fix cucumber spec for loading tasks from stage configs (@sponomarev) 66 | * Minor documentation fixes (@deeeki, @seuros, @andresilveira) 67 | * Spec improvements (@dimitrid, @sponomarev) 68 | * Fix to CLI flags for git-ls-remote (@dimitrid) 69 | 70 | ## `3.3.3` 71 | 72 | https://github.com/capistrano/capistrano/compare/v3.2.1...v3.3.3 73 | 74 | * Enhancement (@townsen) 75 | * Added the variable `:repo_tree` which allows the specification of a sub-tree that 76 | will be extracted from the repository. This is useful when deploying a project 77 | that lives in a subdirectory of a larger repository. 78 | Implemented only for git and hg. 79 | If not defined then the behaviour is as previously and the whole repository is 80 | extracted (subject to git-archive `.gitattributes` of course). 81 | 82 | * Enhancement (@townsen): Remove unnecessary entries from default backtrace 83 | 84 | When the `--backtrace` (or `--trace`) command line option is not supplied 85 | Rake lowers the noise level in exception backtraces by building 86 | a regular expression containing all the system library paths and 87 | using it to exclude backtrace entries that match. 88 | 89 | This does not always go far enough, particularly in RVM environments when 90 | many gem paths are added. This commit reverses that approach and _only_ 91 | include backtrace entries that fall within the Capfile and list of tasks 92 | imported thereafter. This makes reading exceptions much easier on the eye. 93 | 94 | If the full unexpurgated backtrace is required then the --backtrace 95 | and --trace options supply it as before. 96 | 97 | * Disable loading stages configs on `cap -T` (@sponomarev) 98 | 99 | * Enhancements (@townsen) 100 | * Fix matching on hosts with custom ports or users set 101 | * Previously filtering would affect any generated configuration files so that 102 | files newly deployed would not be the same as those on the hosts previously 103 | deployed (and now excluded by filters). This is almost certainly not what is 104 | wanted: the filters should apply only to the on() method and thus any 105 | configuration files deployed will be identical across the set of servers 106 | making up the stage. 107 | * Host and Role filtering now affects only `on()` commands 108 | and not the `roles()`, `release_roles()` and `primary()` methods. 109 | * This applies to filters defined via the command line, the environment 110 | and the :filter variable. 111 | * Filtering now supports Regular expressions 112 | * This change _could_ cause existing scripts that use filtering and depend on 113 | the old behaviour to fail, though it is unlikely. Users who rely on 114 | filtering should check that generated configuration files are correct, and 115 | where not introduce server properties to do the filtering. For example, if a 116 | filter was used to specify an active subset of servers (by hostname), it should 117 | be removed and replaced with an 'active' property (set to true or false) on the 118 | server definitions. This keeps the stage file as the canonical model of the 119 | deployment environment. 120 | 121 | * See the documentation in the README.md file 122 | 123 | * Enhancements (@townsen) 124 | * Added set_if_empty method to DSL to allow conditional setting 125 | * Altered standard Capistrano defaults so that they are not set 126 | at the start of a stage if they have been previously set. This 127 | allows variables like :default_env to be set in deploy.rb. 128 | * Deep copy properties added using the 'roles' keyword 129 | * If a property exists on a server when another definition is 130 | encountered and is an Array, Set or Hash then add the new values 131 | 132 | This allows roles to specify properties common to all servers and 133 | then for individual servers to modify them, keeping things DRY 134 | 135 | Breaking Changes: 136 | * By using Ruby's noecho method introduced in Ruby version 1.9.3, we dropped support for Ruby versions prior to 1.9.3. See [issue #878](https://github.com/capistrano/capistrano/issues/878) and [PR #1112](https://github.com/capistrano/capistrano/pull/1112) for more information. (@kaikuchn) 137 | * Track (anonymous) statistics, see https://github.com/capistrano/stats. This breaks automated deployment on continuous integration servers until the `.capistrano/metrics` file is created (with content `full` to simulate a "yes") via the interactive prompt or manually. 138 | 139 | * Bug Fixes: 140 | * Fixed compatibility with FreeBSD tar (@robbertkl) 141 | * remote_file can be used inside a namespace (@mikz) 142 | 143 | * Minor Changes 144 | * Remove -v flag from mkdir call. (@caligo-mentis) 145 | * Capistrano now allows to customize `local_user` for revision log. (@sauliusgrigaitis) 146 | * Added tests for after/before hooks features (@juanibiapina, @miry) 147 | * Added `--force` flag to `svn export` command to fix errors when the release directory already exists. 148 | * Improved the output of `cap --help`. (@mbrictson) 149 | * Cucumber suite now runs on the latest version of Vagrant (@tpett) 150 | * The `ask` method now supports the `echo: false` option. (@mbrictson, @kaikuchn) 151 | * Cucumber scenario improvements (@bruno-) 152 | * Added suggestion to Capfile to use 'capistrano-passenger' gem, replacing suggestion in config/deploy.rb to re-implement 'deploy:restart' (@betesh) 153 | * Updated svn fetch_revision method to use `svnversion` 154 | * `cap install` no longer overwrites existing files. (@dmarkow) 155 | 156 | ## `3.2.1` 157 | 158 | https://github.com/capistrano/capistrano/compare/v3.2.0...v3.2.1 159 | 160 | * Bug Fixes: 161 | * 3.2.0 introduced some behaviour to modify the way before/after hooks were called, to allow the optional 162 | preservation of arguments to be passed to tasks. This release reverts that commit in order to restore 163 | original functionality, and fix (fairly serious) bugs introduced by the refactoring. 164 | 165 | * Minor changes: 166 | * Update dsl#local_user method and add test for it. (@bruno-) 167 | * Revert short sha1 revision with git. (@blaugueux) 168 | * Changed asking question to more standard format (like common unix commandline tools) (@sponomarev) 169 | * Fixed typos in the README. (@sponomarev) 170 | * Added `keys` method to Configuration to allow introspection of configuration options. (@juanibiapina) 171 | * Improve error message when git:check fails (raise instead of silently `exit 1`) (@mbrictson) 172 | 173 | ## `3.2.0` 174 | 175 | The changelog entries here are incomplete, because many authors choose not to 176 | be credited for their work, check the tag comparison link for Github. 177 | 178 | https://github.com/capistrano/capistrano/compare/v3.1.0...v3.2.0 179 | 180 | * Minor changes: 181 | * Added `keys` method to Server properties to allow introspection of automatically added 182 | properties. 183 | * Compatibility with Rake 10.2.0 - `ensure_task` is now added to `@top_level_tasks` as a string. (@dmarkow) 184 | * Amended the git check command, "ls-remote", to use "-h", limiting the list to refs/heads 185 | 186 | ## `3.1.0` 187 | 188 | https://github.com/capistrano/capistrano/compare/v3.0.1...v3.1.0 189 | 190 | Breaking changes: 191 | 192 | * `deploy:restart` task **is no longer run by default**. 193 | From this version, developers who restart the app on each deploy need to declare it in their deploy flow (eg `after 'deploy:publishing', 'deploy:restart'`) 194 | or, for passenger applications, use the capistrano-passenger gem. 195 | 196 | Please, check https://github.com/capistrano/capistrano/commit/4e6523e1f50707499cf75eb53dce37a89528a9b0 for more information. (@kirs) 197 | 198 | * Minor changes 199 | * Tasks that used `linked_dirs` and `linked_files` now run on all roles, not just app roles (@mikespokefire) 200 | * Tasks `deploy:linked_dirs`, `deploy:make_linked_dirs`, `deploy:linked_files`, `deploy:cleanup_rollback`, 201 | `deploy:log_revision` and `deploy:revert_release` now use `release_roles()` not `roles()` meaning that they 202 | will only run on servers where the `no_release` property is not falsy. (@leehambley) 203 | * Fixed bug when `deploy:cleanup` was executed twice by default (@kirs) 204 | * Config location can now be changed with `deploy_config_path` and `stage_config_path` options (@seenmyfate) 205 | * `no_release` option is now available (@seenmyfate) 206 | * Raise an error if developer tries to define `:all` role, which is reserved (@kirs) 207 | * `deploy:failed` hook was added to add some custom behaviour on failed deploy (@seenmyfate) 208 | * Correctly infer namespace in task enhancements (@seenmyfate) 209 | * Add SHA to revision log (@blackxored) 210 | * Allow configuration of multiple servers with same hostname but different ports (@rsslldnphy) 211 | * Add command line option to control role filtering (@andytinycat) 212 | * Make use of recent changes in Rake to over-ride the application name (@shime) 213 | * Readme corrections (@nathanstitt) 214 | * Allow roles to be fetched with a variable containing an array (@seenmyfate) 215 | * Improve console (@jage) 216 | * Add ability to filter tasks to specific servers (host filtering). (@andytinycat) 217 | * Add a command line option to control role filter (`--roles`) (@andytinycat) 218 | * Use an SCM object with a pluggable strategy (@coffeeaddict) 219 | 220 | Big thanks to @Kriechi for his help. 221 | 222 | ## `3.0.1` 223 | 224 | https://github.com/capistrano/capistrano/compare/v3.0.0...v3.0.1 225 | 226 | * `capify` not listed as executable (@leehambley) 227 | * Confirm license as MIT (@leehambley) 228 | * Move the git ssh helper to application path (@mpapis) 229 | 230 | ## `3.0.0` 231 | 232 | https://github.com/capistrano/capistrano/compare/2.15.5...v3.0.0 233 | 234 | If you are coming here to wonder why your Capfile doesn't work anymore, please 235 | vendor lock your Capistrano at 2.x, whichever version was working for you 236 | until today. 237 | 238 | Capistrano 3 is a ground-up rewrite with modularity, stability, speed and 239 | future proofing in mind. It's a big change, but now the code is 10x smaller, 240 | runs faster, is easier to read, and quicker to extend. In the reduction we've 241 | come up with a great gem based modular system for plugins and we're really 242 | proud of this release. 243 | 244 | The 3.0.0 release contains 38 patches from the following amazing people: 245 | 246 | * Tom `seenmyfate` Clements: more than 28 patches including cucumber integration tests! Not to 247 | mention Rails asset pipeline code, and bundler integrations. 248 | * Lee Hambley: Small changes around compatibility and log formatting 249 | * Kir Shatrov: for improvements in the core to make it easier to write extensions, for 250 | improving documentation, and for effectively building the chruby, rvm and rbenv integrations. 251 | * Michael Nikitochkin: Fixing a bug around linked files and directories. 252 | * Jack Thorne: for improvements to the default `Capfile` to fix some bad example syntax. 253 | * Erik Hetzner: for (what looks like great) work on the Mercurial (Hg) support. The Hg and Git 254 | source control mechanisms do not work the same way, but rather lean on the strengths of the 255 | underlying tools. 256 | 257 | (If I missed anyone, I'm sorry, your contributions have been awesome) 258 | 259 | The 2.x branch of code is now no longer maintained. Towards the end of it's 260 | useful life there were an increasing number of features and pieces of code 261 | which didn't make sense for certain groups of people, in certain situations, 262 | leading a to a ping-pong tennis effect with pull requests every few weeks 263 | "fixing" a use-case which had already been "fixed" shortly before. As many of 264 | the use-cases are outside the scope of the testing environments I (and by 265 | extension the trusted contributors and IRC regulars) were able to test for. 266 | 267 | There's a more extensive post about my failure to be able to keep up with the 268 | demands of maintaining v2 whilst trying to build something which is appropriate 269 | for the current landscape. If you are affected by the unsupported 2 branch, 270 | please contact me (Lee Hambley) to discuss how my company can help support you. 271 | Otherwise, please try v3, we're sure you'll like it, and the code is designed 272 | to be so simple that anyone can work on it. 273 | 274 | ## `3.0.0.pre14` 275 | 276 | * Thanks to numerous contributors, in particular (@teohm) for a series of improvements. 277 | 278 | ## `3.0.0.pre13` 279 | 280 | * Fixed typos in the Capfile. (@teohm) 281 | * Allow setting SSH options globally. (@korin) 282 | * Change the flow (and hooks) see http://www.capistranorb.com/documentation/getting-started/flow/ for more information. Requires min SSHKit 0.0.34 (@teohm) 283 | * Fix sorting releases in lexicographical order (@teohm) 284 | 285 | ## `3.0.0.pre12` 286 | 287 | * `capistrano/bundler` now runs bundle on all roles, this addresses the same 288 | issue as the related changes in `pre11`. (@leehambley) 289 | 290 | ## `3.0.0.pre11` 291 | 292 | * Some deploy.rake tasks now apply to all servers, not expecting a 293 | primary(:app) server which may not exist in all deploy environments. 294 | (@leehambley). 295 | 296 | ## `3.0.0.pre10` 297 | 298 | * Fixes pre9. 299 | 300 | ## `3.0.0.pre9` 301 | 302 | * Fixes a syntax error introduced with filtering (with tests) introduced in 303 | `pre8`. (@leehambley) 304 | 305 | ## `3.0.0.pre8` 306 | 307 | * Fixed a syntax where `roles(:foo, :bar)` was being mistaken as a filter 308 | (roles(:foo, :bar => nil). The correct syntax to use is: roles([:foo,:bar]) 309 | (@leehambley) 310 | 311 | ## `3.0.0.pre7` 312 | 313 | * Fix Git https authentication. (@leehambley) 314 | * Capfile template fixes (repo/repo_url) (@teohm) 315 | * Readme Fixes (@ffmike, @kejadlen, @dwickwire) 316 | * Fix the positioning of the bundler hook, now immediately after finalize. (@teohm) 317 | -------------------------------------------------------------------------------- /test/fixtures/changelog/carrierwave.md: -------------------------------------------------------------------------------- 1 | # Carrierwave History/Changelog 2 | 3 | ## Version 0.10.0 2014-02-26 4 | 5 | * [changed] Memoize uploaders and uploader_options (Derek Parker and Joshua Davey from Hashrocket) 6 | * [changed] Don't force pad background color to white in `resize_and_pad` (@fnordfish) 7 | * [changed] Remove auth access information when parsing URL for filename (@nddeluca) 8 | * [changed] Read Content type from cached and uploaded file, adds mime-types as hard dependency 9 | * [added] Added authenticated_url functionality for Openstack storage (@snoopie) 10 | * [added] Add Polish I18n translations for errors (@ArturT) 11 | * [added] Add Greek locale for error messages (@agorf) 12 | * [added] Add French locale for error messages (@gdurelle) 13 | * [added] Add Japanese locale for error messages (@tomodian) 14 | * [added] Add Norwegian locale for error messages (@theodorton) 15 | * [added] Add Portuguese locale for error messages (@pedrosmmoreira) 16 | * [fixed] Overridden serializable_hash accepts an options hash (@bensie) 17 | * [fixed] Fog connection object performance issues (@taavo) 18 | * [fixed] Delete Tempfile after manipulate with MiniMagick (@dimko) 19 | * [fixed] Ensure `#remove_#{column}` and `#remove_#{column}` return false after committing with ActiveRecord (@bensie) 20 | * [fixed] Fix issue with content-disposition existing with no filename when downloading, reports that Google does this (@hasghari / @bensie / @taavo) 21 | 22 | ## Version 0.9.0 2013-07-06 23 | 24 | * [BREAKING CHANGE] Use integer time (UTC) to generate cache IDs [@bensie] 25 | * [changed] Recommend using ActionController::Base.helpers instead of Sprockets::Rails::Helper for asset pipeline [@c0] 26 | * [changed] Lots of URL encoding fixes [@taavo] 27 | * [added] Added #version_exists? method [@tmaier] 28 | * [added] Added configuration param (`:fog_use_ssl_for_aws`) to disable SSL for public_url [@pbzymek] 29 | * [added] Add Dutch i18n translations for errors [@vanderhoorn] 30 | * [added] Add Czech i18n translations for errors [@elmariofredo] 31 | * [added] Add German i18n translations for errors [@felixbuenemann] 32 | * [fixed] Gemspec error in Ruby 2.0.0 [@sanemat] 33 | * [fixed] Fixed bug in serializing to xml or json where both :only and :except are passed [@Knack] 34 | * [fixed] Fix recreate_versions! when version if proc returns false [@arthurnn] 35 | 36 | ## Version 0.8.0 2013-01-08 37 | 38 | * [BREAKING CHANGE] Remove 'fog\_endpoint' in favor of 'host' and/or 'endpoint' in fog_credentials [bensie] 39 | * [changed] Remove autoload in favor of standard 'require' to help with thread safety [bensie] 40 | * [added] Allow recreating only specified versions instead of all versions [div] 41 | * [added] Add support for S3-compliant storage APIs that are not actually S3 [neuhausler] 42 | * [added] Add #extension CarrierWave::Storage::Fog::File for fetching a file extension [sweatypitts] 43 | * [fixed] Marshaling uploader objects no longer raises a TypeError on anonymous classes [bensie] 44 | 45 | ## Version 0.7.1 2012-11-08 46 | 47 | * [added] add a override to allow fog configuration per uploader [dei79] 48 | * [fixed] Fix a regression when removing uploads [mattolson] 49 | 50 | ## Version 0.7.0 2012-10-19 51 | 52 | * [BREAKING CHANGE] Rename 'fog\_host' config option to 'asset_host' and add support for file storage [DouweM] 53 | * [changed] Changed after\_destroy with after\_commit ... :on => :destroy [Cristian Sorinel] 54 | * [changed] Do not handle any special cases for URL handling, keep the existing escape/unescape functionality and allow overriding [bensie] 55 | * [changed] Activerecord-deprecated_finders gem was renamed [bensie] 56 | * [changed] Removed unnecessary present? method from ActiveSupport [Yauheni Kryudziuk] 57 | * [changed] Use AWS S3 subdomain URL when directory name contains a period. [DouweM] 58 | * [added] Added `resize_to_geometry_string` RMagick method that will scale image [wprater] 59 | * [added] Made feature to blacklist certain extensions [thiagofm] 60 | * [added] Parse and pass fog_host option to ::Fog::Storage [Yauheni Kryudziuk] 61 | * [added] Add serialization spec for multiple uploaders. [malclocke] 62 | * [added] Add :read option to manipulate! [xtreme-tanzeeb-khalili] 63 | * [added] Add binary/octet-stream as generic mime type. [phiggins] 64 | * [added] Add 'fog_endpoint' config option to set an alternate Fog host. [DouweM] 65 | * [fixed] Fixed can't convert File into String [jnimety] 66 | * [fixed] Fixed an issue when parsing URL w/o schema. [Yauheni Kryudziuk] 67 | * [fixed] Fix reference to column in serializable_hash [malclocke] 68 | * [fixed] Fix inconsistence in file API [oelmekki] 69 | 70 | ## Version 0.6.2 2012-04-12 71 | 72 | * [fixed] Don't double-generate cache_id [skyeagle] 73 | * [added] Escape plus signs (+) in remote URLs [adrianpike] 74 | * [added] Enhance multi-page PDF support in RMagick [xtreme-tanzeeb-khalili] 75 | 76 | ## Version 0.6.1 2012-04-02 77 | 78 | * [fixed] Calling #serializable_hash with no options [matthewrudy] 79 | 80 | ## Version 0.6.0 2012-03-27 81 | 82 | * [BREAKING CHANGE] Require Rails 3.2 or Rails master (4.0) - depends on activesupport/activemodel [bensie] 83 | * [BREAKING CHANGE] Remove :S3 storage option in favor of Fog [bensie] 84 | * [BREAKING CHANGE] Remove :CloudFiles storage option in favor of Fog [bensie] 85 | * [changed] JSON / XML serialization hashes are consistent and work as expected with ActiveRecord's serializable_hash [bensie] 86 | * [added] fog_host now accepts a proc (useful for dynamic asset servers) [jtrim] 87 | * [added] Add ability to process a version from an existing version so you aren't always crunching the original, large file [ferblape] 88 | * [added] Allow brackets in remote URLs [ngauthier] 89 | * [added] CarrierWave::Storage::Fog::File#exists? to check the existence of the file without needing to fetch it [bensie] 90 | * [added] Gravity option on `resize_to_fill` (minimagick) [TheOddLinguist] 91 | * [added] Add query options for s3 to support response headers overwriting [meceo] 92 | * [added] Make storages File#url methods to work without any params [meceo] 93 | * [added] Set the CarrierWave.root correctly if Padrino is defined [futurechimp] 94 | * [added] Cache fog connections for improved performance [labocho] 95 | * [fixed] Fix slow fetching of content-length on remote file [geemus] 96 | * [fixed] Fog remote specs now passing and depend on Fog >= 1.3.1 [geemus] 97 | * [fixed] Fix an issue where multi-page PDFs can't be converted with RMagick [chanind] 98 | * [fixed] MiniMagick expects string args to mogrify commands [bensie] 99 | * [fixed] With Active Record ORM, setting remote_url marks mounted column as dirty [trevorturk] 100 | * [fixed] Fix possible race condition with CarrierWave.root [bensie] 101 | * [fixed] ActiveSupport::Memoizable deprecation warning [slbug] 102 | 103 | ## Version 0.5.8 2011-11-10 104 | 105 | * [added] Allow custom error messages [bartt] 106 | * [added] Add config.base_path to use as a prefix for uploader URLs [die-antwort] 107 | * [added] Support fog streaming uploads [chrisdurtschi] 108 | * [added] Support `move_to` in addition to the default `copy_to` when using the cache [jasonydes] 109 | * [fixed] Support for Sinatra 1.3 (with backward compatibility) [bensie] 110 | * [fixed] Fog `get_object_url` deprecated, use `get_object_https_url` or `get_object_http_url` [scottmessinger] 111 | 112 | ## Version 0.5.7 2011-08-12 113 | 114 | * [BREAKING CHANGE] Extracted Mongoid support into a separate gem (carrierwave-mongoid) [jnicklas] 115 | * [BREAKING CHANGE] Remove ImageScience support due to lack maintenance and 1.9.2 compatibility [jnicklas] 116 | * [BREAKING CHANGE] Combine `delete_tmp_file_after_storage` and `delete_cache_id_after_storage` options [bensie] 117 | * [changed] Cached and then remote-uploaded file will no longer have a content_type, please use CarrierWave::MimeTypes processor instead [trevorturk] 118 | * [changed] Allow writing over a previously assigned file when retrieving a remote file [Florent2] 119 | * [fixed] Fixed exception when nested or double-embedded Mongoid documents are saved [potatosalad] 120 | * [fixed] Fixed that store! can call process! twice [gzigzigzeo] 121 | * [fixed] Performance enhancements by reducing use of rescue [jamescook] 122 | 123 | ## Version 0.5.6 2011-07-12 124 | 125 | * [fixed] Remove cache file and directories after storing [scottwb] 126 | * [fixed] Add missing active_support/deprecation require [trevorturk] 127 | * [fixed] Remove redundant requires of sequel and datamapper [solnic] 128 | * [fixed] Running tests with REMOTE=true [geemus] 129 | 130 | ## Version 0.5.5 2011-07-09 131 | 132 | * [BREAKING CHANGE] Extracted DataMapper support into a separate gem (carrierwave-datamapper) [jnicklas] 133 | * [BREAKING CHANGE] Extracted Sequel support into a separate gem (carrierwave-sequel) [jnicklas] 134 | * [changed] Don't downcase filenames by default [bensie] 135 | * [changed] Orm mount modules default uploader to nil [jnicklas] 136 | * [changed] Remove alias_method :blank? from SanitizedFile to for performance re: issue #298 [trevorturk] 137 | * [added] Conditional processing of versions [gucki] 138 | * [added] Remove Remove previously stored files after Active Record mounted uploader update re: issue #75 [trevorturk] 139 | * [added] Remove Remove previously stored files after Mongoid mounted uploader update re: issue #75 [did] 140 | * [added] Added _identifier to retrieve identifier/filename [jnicklas] 141 | * [added] `clean_cached_files!` clears all files older than 24 hours by default, but time frame can now be customized [cover] 142 | * [added] Versions now implement an enable_processing method which uses the parent when no value is set [mariovisic] 143 | * [added] Delete cache_id garbage dirs, closes GH issue #338 [clyfe] 144 | * [added] Added CarrierWave::MimeTypes processor for more advanced content-type guessing [JangoSteve] 145 | * [fixed] Active Record's `will_change!` method works when `mount_on` option is used [indrekj] 146 | * [fixed] Fixed problem with accepting URL uploads when the URL was already escaped [cover] 147 | * [fixed] Fixed ability to override sanitize_regexp [trevorturk] 148 | * [fixed] Fix that cached and then remote-uploaded file should have content_type [trevorturk] 149 | * [fixed] Fix `validates_size/length_of` in Rails 3.0.6 and above, closes #342 [bensie] 150 | * [fixed] Various Active Support compatibility updates [slbug, bensie, et al] 151 | 152 | ## Version 0.5.4 2011-05-18 153 | 154 | * [changed] Fog: Performance enhancements for AWS and Google [geemus] 155 | * [changed] Fog: Try to use subdomain public url on s3 [geemus] 156 | * [changed] Memoize CarrierWave::Mounter#option for increased performance [ingemar] 157 | * [changed] Relax development gem dependency versions where possible and fix tests [trevorturk] 158 | * [changed] Upgrade to RSpec 2 [jnicklas] 159 | 160 | ## Version 0.5.3 2011-03-22 161 | 162 | * [changed] Cloud Files storage so delete and url return nil if object not found instead of exception [minter] 163 | * [added] New fog storage provider that supports Amazon S3, Rackspace Cloud Files, and Google Storare for Developers [geemus] 164 | * [added] `cloud_files_auth_url` and `cloud_files_snet` config options for Cloud Files [minter] 165 | * [added] process_uri method that can be overridden in your uploader to support downloads from non-standard urls [trevorturk] 166 | * [added] version urls to json output [karb] 167 | * [added] Active Record marks uploader column as changed when changed [josevalim] 168 | * [fixed] Cloud Files storage tests to use the new url format [minter] 169 | * [fixed] Moved raising of FormNotMultipart farther down to avoid errors with nested attribute forms [trevorturk] 170 | * [fixed] original_filename of remote uploads should be calculated from final (possibly redirected) URL [brady8] 171 | * [fixed] Fix calling :process! on files stored in remote solutions [alexcrichton] 172 | * [fixed] Fix paperclip compatibility mappings [valakirka] 173 | * [fixed] Ensure temporary files can be deleted on Windows [Eleo] 174 | 175 | ## Version 0.5.2 2011-02-18 176 | 177 | * [changed] Require `active_support/core_ext/string/multibyte` to fix downcasing unicode filenames during sanitizing [nashbridges] 178 | * [changed] Use fog ~> 0.4, Fog::AWS::Storage.new -> Fog::Storage.new(:provider => 'AWS') [trevorturk] 179 | * [changed] Use class_attribute (inheritable attributes are deprecated) [stephencelis] 180 | * [changed] `extension_white_list` no longer supports a single string, only an array of strings and/or Regexps [trevorturk] 181 | * [changed] Rackspace Cloud Files: only create container if container does not exist [edmundsalvacion] 182 | * [changed] GridFS: the path returned is no longer always nil, it is now the path in GridFS [alexcrichton] 183 | * [added] Ability to specify a Regexp in the `extension_white_list` [lwe] 184 | * [added] CarrierWave::SanitizedFile#sanitize_regexp public method to allow customizing [trevorturk] 185 | * [added] sanitize_regexp documentation to the README [nashbridges] 186 | * [added] Ability to use https for Amazon S3 URLs if `config.s3_use_ssl` is true [recruitmilitary] 187 | * [added] The s3_region configuration documentation to the README [mrsimo] 188 | * [fixed] Reprocessing remotely stored files [alexcrichton] 189 | * [fixed] Nested versioning processing [alexcrichton] 190 | * [fixed] An intermittent bug with ImageScience `resize_to_fill` method [LupineDev] 191 | * [fixed] DataMapper#save should remove the avatar if remove_avatar? returns true [wprater] 192 | 193 | ## Version 0.5.1 2010-12-01 194 | 195 | * [changed] `s3_access` renamed to `s3_access_policy` [Jonas Nicklas] 196 | * [changed] Depend on activesupport ~> 3.0 for Rails 3.1 compatibility [Trevor Turk] 197 | * [changed] Use fog >= 0.3.0, fix deprecation warnings [Paul Elliott] 198 | * [changed] Use `mini_magick ~> 2.3`, `MiniMagick::Image.from_file` becomes `MiniMagick::Image.open` [Fredrik Björk] 199 | * [changed] Convert generic MiniMagick::Invalid into ProcessingError [Alex Crichton] 200 | * [changed] Remove cached tmp file after storing for file store [Damien Mathieu] 201 | * [added] s3_region config option to set AWS S3 region [Roger Campos] 202 | * [added] Option to retain cached tmp file after storage (`delete_tmp_file_after_storage`) [Damien Mathieu] 203 | * [added] Transparent support for authenticated_read on S3 [Jonas Nicklas] 204 | * [fixed] Clean up internal require statements [Josh Kalderimis] 205 | * [fixed] Header support for S3 [Alex Crichton] 206 | * [fixed] Stack level too deep errors when using to_json [Trevor Turk] 207 | * [fixed] Documentation for mount_uploader [Nathan Kleyn] 208 | 209 | ## Version 0.5 2010-09-23 210 | 211 | * [changed] Use ActiveModel instead of ActiveRecord validations to support Mongoid validations as well [Jeroen van Dijk, saberma] 212 | * [changed] Support S3 file storage with the fog gem, instead of the aws gem (Trevor Turk) 213 | * [changed] Move translations to a YAML file (Josh Kalderimis) 214 | * [changed] Depend on activesupport ~> 3.0.0 instead of >= 3.0.0.rc (Trevor Turk) 215 | * [changed] Remove old Merb and Rails generators, support Rails 3 generators (Jonas Nicklas, Trevor Turk) 216 | * [changed] Replace Net::HTTP with open-url for remote file downloads (icebreaker) 217 | * [changed] Move translations to a YAML file (Josh Kalderimis) 218 | * [changed] Use gemspec to generate Gemfile contents (Jonas Nicklas) 219 | * [added] Add file size support for S3 storage (Pavel Chipiga) 220 | * [added] Add option for disabling multipart form check (Dennis Blöte) 221 | * [fixed] Correct naming of validators (Josh Kalderimis) 222 | * [fixed] Fix remote file downloader (Jonas Nicklas) 223 | * [fixed] Escape URLs passed to remote file downloader so URLs with spaces work (Mauricio Zaffari) 224 | * [fixed] Correct filename used in generators (Fred Wu) 225 | 226 | ## Version 0.4.6 2010-07-20 227 | 228 | * [removed] Support for MongoMapper, see: http://groups.google.com/group/carrierwave/browse_thread/thread/56df146b83878c22 229 | * [changed] AWS support now uses the aws gem, instead of using aws-s3 or right-aws as previously 230 | * [added] `cloud_files_cdn_host` for Cloudfiles for performance gain 231 | * [added] #recreate_versions! to recreate versions from base file 232 | * [added] Support for MiniMagick in RSpec matchers 233 | * [added] RMagick's `resize_to_fill` now takes an optional Gravity 234 | * [fixed] Pass through options to to_json 235 | * [fixed] Support new GridFS syntax for lates mongo gem 236 | * [fixed] Validation errors are internationalized when the error is thrown, not on load 237 | * [fixed] Rescue correct MiniMagick error 238 | * [fixed] Support DataMapper 1.0 239 | * [fixed] `SanitizedFile#copy_to` preserves content_type. Should fix GridFS content type not being set. 240 | 241 | ## Version 0.4.5 2010-02-20 242 | 243 | * [added] Support for Rackspace Cloudfiles 244 | * [added] GridFS now accepts a port 245 | * [fixed] s3_headers is now properly initialized 246 | * [fixed] work around DataMapper's patching of core method 247 | 248 | ## Version 0.4.4 2010-01-31 249 | 250 | * [added] Support for downloading remote files 251 | * [added] `CarrierWave.clean_cached_files!` to remove old cached files 252 | * [added] Option to set headers for S3 253 | * [added] GridStore now has authentication 254 | * [fixed] Rmagick convert method now does what it says 255 | * [fixed] Content type is stored on GridStore and Amazon S3 256 | * [fixed] Metadata is no longer broken for S3 257 | 258 | ## Version 0.4.3 2009-12-19 259 | 260 | * [fixed] cnamed URLs on S3 no longer have a third slash after http 261 | * [fixed] fixed deprecation warnings on Rails 2.3.5 262 | 263 | ## Version 0.4.2 2009-11-26 264 | 265 | * [added] RightAWS as an alternative S3 implementation 266 | * [added] An option to enable/disable processing for tests 267 | * [added] Mongoid ORM support 268 | * [fixed] DataMapper now works both with and without dm-validations 269 | 270 | ## Version 0.4.1 2009-10-26 271 | 272 | * [changed] Major changes to the ImageScience module, it actually works now! 273 | * [fixed] Bug in configuration where it complais that it can't dup Symbol 274 | 275 | * [removed] Support for Sequel < 2.12 276 | * [removed] `crop_resized` and `resize` aliases in RMagick, use `resize_to_fill` and `resize_to_fit` respectively 277 | 278 | ## Version 0.4.0 2009-10-12 279 | 280 | * [changed] the `public` option has been renamed `root` and the old `root` option was removed. No more ambiguity. 281 | * [changed] Major *breaking* changes to the configuration syntax. 282 | 283 | * [removed] support for `default_path` 284 | * [removed] the `cache_to_cache_dir` option 285 | * [removed] storage no longer calls `setup!` on storage engines 286 | 287 | * [added] Support for MongoDB's GridFS store 288 | 289 | ## Version 0.3.4 2009-09-01 290 | 291 | * [added] `default_url` as a replacement for `default_path` 292 | * [deprecated] `default_path` is deprecated 293 | 294 | ## Version 0.3.4 2009-08-31 295 | 296 | * [fixed] Deleting no longer causes TypeError in MongoMapper 297 | 298 | ## Version 0.3.3 2009-08-29 299 | 300 | * [added] Support for MongoMapper 301 | * [added] Support for CNamed Bucket URLs for Amazon S3 302 | 303 | ## Version 0.3.2 2009-07-18 304 | 305 | Incremental upgrade 306 | 307 | * [added] Ruby 1.9 compatibility 308 | * [changed] Added Object#blank? implementation into CarrierWave, which removes any dpendencies on external libraries (extlib/activesupport) 309 | * [fixed] Performance issues with S3 support 310 | * [fixed] Sequel support for newer verions of Sequel (thanks Pavel!) 311 | 312 | ## Version 0.3.1 2009-07-01 313 | 314 | A bugfix release. Drop in compatible with 0.3.0. 315 | 316 | * [fixed] Saving a record with a mounted Uploader no longer removes uploaded file 317 | * [fixed] The file returned by S3 storage now has the path set to the full store path 318 | * [added] File returned by S3 storage now responds to S3 specific methods 319 | 320 | ## 0.3 2009-06-20 321 | 322 | This is a stabilization release. Most features are now working as expected and 323 | most bugs should be fixed. 324 | 325 | * [changed] Reworked how storage engines work, some internal API changes 326 | * [added] Macro-like methods for RMagick, no need to call #process any more! 327 | * [added] Ability to super to any Mount method 328 | * [fixed] Sequel support should now work as expected 329 | * [fixed] ActiveRecord no longer saves the record twice 330 | * [added] Added convenient macro style class methods to rmagick processing 331 | 332 | ## 0.2.4 2009-06-11 333 | 334 | * [added] `resize_to_limit` method for rmagick 335 | * [added] Now deletes files from Amazon S3 when record is destroyed 336 | 337 | ## 0.2.3 2009-05-13 338 | 339 | * [changed] Mount now no longer returns nil if there is no stored file, it returns a blank uploader instead 340 | * [added] Possibility to specify a default path 341 | * [added] Paperclip compatibility module 342 | 343 | ## 0.2.1 2009-05-01 344 | 345 | * [changed] Url method now optionally takes versions as parameters (like Paperclip) 346 | * [added] A field which allows files to be removed with a checkbox in mount 347 | * [added] Mount_on option for Mount, to be able to override the serialization column 348 | * [added] Added demeter friendly column_url method to Mount 349 | * [added] Option to not copy files to cache dir, to prevent writes on read only fs systems (this is a workaround and needs a better solution) 350 | 351 | ## 0.2 2009-04-15 352 | 353 | * [changed] The version is no longer stored in the store dir. This will break the paths for files uploaded with 0.1 354 | * [changed] CarrierWave::Uploader is now a module, not a class, so you need to include it, not inherit from it. 355 | * [added] integrity checking in uploaders via a white list of extensions 356 | * [added] Validations for integrity and processing in ActiveRecord, activated by default 357 | * [added] Support for nested versions 358 | * [added] Permissions option to set the permissions of the uploaded files 359 | * [added] Support for Sequel 360 | * [added] CarrierWave::Uploader#read to read the contents of the uploaded files 361 | 362 | ## 0.1 2009-03-12 363 | 364 | This is a very experimental release that has not been well tested. All of the major features are in place though. Please note that there currently is a bug with load paths in Merb, which means you need to manually require uploaders. 365 | -------------------------------------------------------------------------------- /test/fixtures/changelog/activeadmin.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Unreleased 4 | 5 | ### Security Fixes 6 | 7 | * Prevent leaking hashed passwords via user CSV export and adds a config option for sensitive attributes. [#5486] by [@chrp] 8 | 9 | ### Removals 10 | 11 | * Rails 4.2 support has been dropped. [#5104] by [@javierjulio] and [@deivid-rodriguez] 12 | * Dependency on coffee-rails has been removed. [#5081] by [@javierjulio] 13 | If your application uses coffescript but was relying on ActiveAdmin to provide 14 | the dependency, you need to add the `coffee-script` gem to your `Gemfile` to 15 | restore it. If your only usage of coffescript was the 16 | `active_admin.js.coffee` generated by ActiveAdmin's generator, you can also 17 | convert that file to plain JS (`//= require active_admin/base` if you 18 | didn't add any stuff to it). 19 | 20 | ## 1.4.2 [☰](https://github.com/activeadmin/activeadmin/compare/v1.4.1...v1.4.2) 21 | 22 | ### Bug Fixes 23 | 24 | * Fix `input_html` filter option evaluated only once. [#5377] by [@kjeldahl] 25 | 26 | ## 1.4.1 [☰](https://github.com/activeadmin/activeadmin/compare/v1.4.0...v1.4.1) 27 | 28 | ### Bug Fixes 29 | 30 | * Fix menu item link with method delete. [#5583] by [@tiagotex] 31 | 32 | ## 1.4.0 [☰](https://github.com/activeadmin/activeadmin/compare/v1.3.1...v1.4.0) 33 | 34 | ### Enhancements 35 | 36 | #### Minor 37 | 38 | * Add missing I18n for comments. [#5458], [#5461] by [@mauriciopasquier] 39 | * Fix batch_actions.delete_confirmation translation in zh-CN.yml. [#5453] by [@ShallmentMo] 40 | * Add some missing italian translations. [#5433] by [@stefsava] 41 | * Enhance some chinese translations. [#5413] by [@shouya] 42 | * Add missing filter predicate translations to nb. [#5357] by [@rogerkk] 43 | * Add missing norwegian comment translations. [#5375] by [@rogerkk] 44 | * Add missing dutch translations. [#5368] by [@dennisvdvliet] 45 | * Add missing german translations. [#5341] by [@eikes] 46 | * Add missing spanish translation. [#5336] by [@mconiglio] 47 | * Add from and to predicates for russian language. [#5330] by [@glebtv] 48 | * Fix typo in finnish translation. [#5320] by [@JiiHu] 49 | * Add missing turkish translations. [#5295] by [@kobeumut] 50 | * Add missing chinese translations. [#5266] by [@jasl] 51 | * Allow proc label in datepicker input. [#5408] by [@tiagotex] 52 | * Add `group` attribute to scopes in order to show them in grouped. [#5359] by [@leio10] 53 | * Add missing polish translations and improve existing ones. [#5537] by [@Wowu] 54 | * Add `priority` option to `action_item`. [#5334] by [@andreslemik] 55 | 56 | ### Bug Fixes 57 | 58 | * Fixed the string representation of the resolved `sort_key` when no explicit `sortable` attribute is passed. [#5464] by [@chumakoff] 59 | * Fixed docs on the column `sortable` attribute (which actually doesn't have to be explicitly specified when a block is passed to column). [#5464] by [@chumakoff] 60 | * Fixed `if:` scope option when a lambda is passed. [#5501] by [@deivid-rodriguez] 61 | * Comment validation adding redundant errors when resource is missing. [#5517] by [@deivid-rodriguez] 62 | * Fixed resource filtering by association when the resource has custom primary key. [#5446] by [@wasifhossain] 63 | * Fixed "create anoter" checkbox styling. [#5324] by [@faucct] 64 | 65 | ## 1.3.1 [☰](https://github.com/activeadmin/activeadmin/compare/v1.3.0...v1.3.1) 66 | 67 | ### Bug Fixes 68 | 69 | * gemspec should have more permissive ransack dependency. [#5448] by [@varyonic] 70 | 71 | ## 1.3.0 [☰](https://github.com/activeadmin/activeadmin/compare/v1.2.1...v1.3.0) 72 | 73 | ### Enhancements 74 | 75 | #### Major 76 | 77 | * Rails 5.2 support [#5343] by [@varyonic], [#5399], [#5401] by [@zorab47] 78 | 79 | ## 1.2.1 [☰](https://github.com/activeadmin/activeadmin/compare/v1.2.0...v1.2.1) 80 | 81 | ### Bug Fixes 82 | 83 | * Resolve issue with [#5275] preventing XSS in filters sidebar. [#5299] by [@faucct] 84 | 85 | ## 1.2.0 [☰](https://github.com/activeadmin/activeadmin/compare/v1.1.0...v1.2.0) 86 | 87 | ### Enhancements 88 | 89 | #### Minor 90 | 91 | * Do not display pagination info when there are no comments. [#5119] by [@alex-bogomolov] 92 | * Revert generated config files to pluralized. [#5120] by [@varyonic], [#5137] by [@deivid-rodriguez] 93 | * Warn when action definition overwrites controller method. [#5167] by [@aarek] 94 | * Better performance of comments show view. [#5208] by [@dhyegofernando] 95 | * Mitigate memory bloat [#4118] with CSV exports. [#5251] by [@f1sherman] 96 | * Fix issue applying custom decorations. [#5253] by [@faucct] 97 | * Brazilian locale updated. [#5125] by [@renotocn] 98 | * Japanese locale updated. [#5143] by [@5t111111], [#5157] by [@innparusu95] 99 | * Italian locale updated. [#5180] by [@blocknotes] 100 | * Swedish locale updated. [#5187] by [@jawa] 101 | * Vietnamese locale updated. [#5194] by [@Nguyenanh] 102 | * Esperanto locale added. [#5210] by [@RobinvanderVliet] 103 | 104 | ### Bug Fixes 105 | 106 | * Fix a couple of issues rendering filter labels. [#5223] by [@wspurgin] 107 | * Prevent NameError when filtering on a namespaced association. [#5240] by [@DanielHeath] 108 | * Fix undefined method error in Ransack when building filters. [#5238] by [@wspurgin] 109 | * Fixed [#5198] Prevent XSS on sidebar's current filter rendering. [#5275] by [@deivid-rodriguez] 110 | * Sanitize display_name. [#5284] by [@markstory] 111 | 112 | ## 1.1.0 [☰](https://github.com/activeadmin/activeadmin/compare/v1.0.0...v1.1.0) 113 | 114 | ### Bug Fixes 115 | 116 | * Fixed [#5093] Handle table prefix & table suffix for `ActiveAdminComment` model 117 | * Fixed [#4173] by including the default Kaminari templates. [#5069] by [@javierjulio] 118 | * Fixed [#5043]. Do not crash in sidebar rendering when a default scope is not specified. [#5044] by [@Fivell] 119 | * Fixed [#3894]. Make tab's component work with non-ascii titles. [#5046] by [@Fivell] 120 | 121 | ### Removals 122 | 123 | * Ruby 2.1 support has been dropped. [#5003] by [@deivid-rodriguez] 124 | * Replaced `sass-rails` with `sass` dependency. [#5037] by [@javierjulio] 125 | * Removed `jquery-ui-rails` as a dependency. [#5052] by [@javierjulio] 126 | The specific jQuery UI assets used are now within the vendor directory. This 127 | will be replaced by alternatives and dropped entirely in a major release. 128 | Please remove any direct inclusions of `//= require jquery-ui`. This allows us 129 | to upgrade to jquery v3. 130 | 131 | ### Deprecations 132 | 133 | * Deprecated `config.register_stylesheet` and `config.register_javascript`. Import your CSS and JS files in `active_admin.scss` or `active_admin.js`. [#5060] by [@javierjulio] 134 | * Deprecated `type` param from `status_tag` and related CSS classes [#4989] by [@javierjulio] 135 | * The method signature has changed from: 136 | 137 | ```ruby 138 | status_tag(status, :ok, class: 'completed', label: 'on') 139 | ``` 140 | 141 | to: 142 | 143 | ```ruby 144 | status_tag(status, class: 'completed ok', label: 'on') 145 | ``` 146 | 147 | * The following CSS classes have been deprecated and will be removed in the future: 148 | 149 | ```css 150 | .status_tag { 151 | &.ok, &.published, &.complete, &.completed, &.green { background: #8daa92; } 152 | &.warn, &.warning, &.orange { background: #e29b20; } 153 | &.error, &.errored, &.red { background: #d45f53; } 154 | } 155 | ``` 156 | 157 | ### Enhancements 158 | 159 | #### Minor 160 | 161 | * Support proc as an input_html option value when declaring filters. [#5029] by [@Fivell] 162 | * Base localization support, better associations handling for active filters sidebar. [#4951] by [@Fivell] 163 | * Allow AA scopes to return paginated collections. [#4996] by [@Fivell] 164 | * Added `scopes_show_count` configuration to setup show_count attribute for scopes globally. [#4950] by [@Fivell] 165 | * Allow custom panel title given with `attributes_table`. [#4940] by [@ajw725] 166 | * Allow passing a class to `action_item` block. [#4997] by [@Fivell] 167 | * Add pagination to the comments section. [#5088] by [@alex-bogomolov] 168 | 169 | ## 1.0.0 [☰](https://github.com/activeadmin/activeadmin/compare/v0.6.3...master) 170 | 171 | ### Breaking Changes 172 | 173 | * Rename `allow_comments` to `comments` for more consistent naming. [#3695] by [@pranas] 174 | * JavaScript `window.AA` has been removed, use `window.ActiveAdmin`. [#3606] by [@timoschilling] 175 | * `f.form_buffers` has been removed. [#3486] by [@varyonic] 176 | * Iconic has been removed. [#3553] by [@timoschilling] 177 | * `config.show_comments_in_menu` has been removed, see `config.comments_menu`. [#4187] by [@drn] 178 | * Rails 3.2 & Ruby 1.9.3 support has been dropped. [#4848] by [@deivid-rodriguez] 179 | * Ruby 2.0.0 support has been dropped. [#4851] by [@deivid-rodriguez] 180 | * Rails 4.0 & 4.1 support has been dropped. [#4870] by [@deivid-rodriguez] 181 | 182 | ### Enhancements 183 | 184 | #### Major 185 | 186 | * Migration from Metasearch to Ransack. [#1979] by [@seanlinsley] 187 | * Rails 4 support. [#2326] by many people :heart: 188 | * Rails 4.2 support. [#3731] by [@gonzedge] and [@timoschilling] 189 | * Rails 5 support. [#4254] by [@seanlinsley] 190 | * Rails 5.1 support. [#4882] by [@varyonic] 191 | 192 | #### Minor 193 | 194 | * "Create another" checkbox for the new resource page. [#4477] by [@bolshakov] 195 | * Page supports belongs_to. [#4759] by [@Fivell] and [@zorab47] 196 | * Support for custom sorting strategies. [#4768] by [@Fivell] 197 | * Stream CSV downloads as they're generated. [#3038] by [@craigmcnamara] 198 | * Disable streaming in development for easier debugging. [#3535] by [@seanlinsley] 199 | * Improved code reloading. [#3783] by [@chancancode] 200 | * Do not auto link to inaccessible actions. [#3686] by [@pranas] 201 | * Allow to enable comments on per-resource basis. [#3695] by [@pranas] 202 | * Unify DSL for index `actions` and `actions dropdown: true`. [#3463] by [@timoschilling] 203 | * Add DSL method `includes` for `ActiveRecord::Relation#includes`. [#3464] by [@timoschilling] 204 | * BOM (byte order mark) configurable for CSV download. [#3519] by [@timoschilling] 205 | * Column block on table index is now sortable by default. [#3075] by [@dmitry] 206 | * Allow Arbre to be used inside ActiveAdmin forms. [#3486] by [@varyonic] 207 | * Make AA ORM-agnostic. [#2545] by [@johnnyshields] 208 | * Add multi-record support to `attributes_table_for`. [#2544] by [@zorab47] 209 | * Table CSS classes are now prefixed to prevent clashes. [#2532] by [@TimPetricola] 210 | * Allow Inherited Resources shorthand for redirection. [#2001] by [@seanlinsley] 211 | 212 | ```ruby 213 | controller do 214 | # Redirects to index page instead of rendering updated resource 215 | def update 216 | update!{ collection_path } 217 | end 218 | end 219 | ``` 220 | 221 | * Accept block for download links. [#2040] by [@potatosalad] 222 | 223 | ```ruby 224 | index download_links: ->{ can?(:view_all_download_links) || [:pdf] } 225 | ``` 226 | 227 | * Comments menu can be customized via configuration passed to `config.comments_menu`. [#4187] by [@drn] 228 | * Added `config.route_options` to namespace to customize routes. [#4731] by [@stereoscott] 229 | 230 | ### Security Fixes 231 | 232 | * Prevents access to formats that the user not permitted to see. [#4867] by [@Fivell] and [@timoschilling] 233 | * Prevents potential DOS attack via Ruby symbols. [#1926] by [@seanlinsley] 234 | * [this isn't an issue for those using Ruby >= 2.2](http://rubykaigi.org/2014/presentation/S-NarihiroNakamura) 235 | 236 | ### Bug Fixes 237 | 238 | * Fixes filters for `has_many :through` relationships. [#2541] by [@shekibobo] 239 | * "New" action item now only shows up on the index page. bf659bc by [@seanlinsley] 240 | * Fixes comment creation bug with aliased resources. 9a082486 by [@seanlinsley] 241 | * Fixes the deletion of `:if` and `:unless` from filters. [#2523] by [@PChambino] 242 | 243 | ### Deprecations 244 | 245 | * `ActiveAdmin::Event` (`ActiveAdmin::EventDispatcher`). [#3435] by [@timoschilling] 246 | `ActiveAdmin::Event` will be removed in a future version, ActiveAdmin switched 247 | to use `ActiveSupport::Notifications` 248 | NOTE: The blog parameters has changed: 249 | 250 | ```ruby 251 | ActiveSupport::Notifications.subscribe ActiveAdmin::Application::BeforeLoadEvent do |event, *args| 252 | # some code 253 | end 254 | 255 | ActiveSupport::Notifications.publish ActiveAdmin::Application::BeforeLoadEvent, "some data" 256 | ``` 257 | 258 | ## Previous Changes 259 | 260 | Please check [0-6-stable] for previous changes. 261 | 262 | [0-6-stable]: https://github.com/activeadmin/activeadmin/blob/0-6-stable/CHANGELOG.md 263 | 264 | [#1926]: https://github.com/activeadmin/activeadmin/issues/1926 265 | [#1979]: https://github.com/activeadmin/activeadmin/issues/1979 266 | [#2001]: https://github.com/activeadmin/activeadmin/issues/2001 267 | [#2040]: https://github.com/activeadmin/activeadmin/issues/2040 268 | [#2326]: https://github.com/activeadmin/activeadmin/issues/2326 269 | [#2523]: https://github.com/activeadmin/activeadmin/issues/2523 270 | [#2532]: https://github.com/activeadmin/activeadmin/issues/2532 271 | [#2541]: https://github.com/activeadmin/activeadmin/issues/2541 272 | [#2544]: https://github.com/activeadmin/activeadmin/issues/2544 273 | [#2545]: https://github.com/activeadmin/activeadmin/issues/2545 274 | [#3038]: https://github.com/activeadmin/activeadmin/issues/3038 275 | [#3075]: https://github.com/activeadmin/activeadmin/issues/3075 276 | [#3463]: https://github.com/activeadmin/activeadmin/issues/3463 277 | [#3464]: https://github.com/activeadmin/activeadmin/issues/3464 278 | [#3486]: https://github.com/activeadmin/activeadmin/issues/3486 279 | [#3519]: https://github.com/activeadmin/activeadmin/issues/3519 280 | [#3535]: https://github.com/activeadmin/activeadmin/issues/3535 281 | [#3553]: https://github.com/activeadmin/activeadmin/issues/3553 282 | [#3606]: https://github.com/activeadmin/activeadmin/issues/3606 283 | [#3686]: https://github.com/activeadmin/activeadmin/issues/3686 284 | [#3695]: https://github.com/activeadmin/activeadmin/issues/3695 285 | [#3731]: https://github.com/activeadmin/activeadmin/issues/3731 286 | [#3783]: https://github.com/activeadmin/activeadmin/issues/3783 287 | [#3894]: https://github.com/activeadmin/activeadmin/issues/3894 288 | [#4118]: https://github.com/activeadmin/activeadmin/issues/4118 289 | [#4173]: https://github.com/activeadmin/activeadmin/issues/4173 290 | [#4187]: https://github.com/activeadmin/activeadmin/issues/4187 291 | [#4254]: https://github.com/activeadmin/activeadmin/issues/4254 292 | [#5043]: https://github.com/activeadmin/activeadmin/issues/5043 293 | [#5198]: https://github.com/activeadmin/activeadmin/issues/5198 294 | 295 | [#3435]: https://github.com/activeadmin/activeadmin/pull/3435 296 | [#4477]: https://github.com/activeadmin/activeadmin/pull/4477 297 | [#4731]: https://github.com/activeadmin/activeadmin/pull/4731 298 | [#4759]: https://github.com/activeadmin/activeadmin/pull/4759 299 | [#4768]: https://github.com/activeadmin/activeadmin/pull/4768 300 | [#4848]: https://github.com/activeadmin/activeadmin/pull/4848 301 | [#4851]: https://github.com/activeadmin/activeadmin/pull/4851 302 | [#4867]: https://github.com/activeadmin/activeadmin/pull/4867 303 | [#4870]: https://github.com/activeadmin/activeadmin/pull/4870 304 | [#4882]: https://github.com/activeadmin/activeadmin/pull/4882 305 | [#4940]: https://github.com/activeadmin/activeadmin/pull/4940 306 | [#4950]: https://github.com/activeadmin/activeadmin/pull/4950 307 | [#4951]: https://github.com/activeadmin/activeadmin/pull/4951 308 | [#4989]: https://github.com/activeadmin/activeadmin/pull/4989 309 | [#4996]: https://github.com/activeadmin/activeadmin/pull/4996 310 | [#4997]: https://github.com/activeadmin/activeadmin/pull/4997 311 | [#5003]: https://github.com/activeadmin/activeadmin/pull/5003 312 | [#5029]: https://github.com/activeadmin/activeadmin/pull/5029 313 | [#5037]: https://github.com/activeadmin/activeadmin/pull/5037 314 | [#5044]: https://github.com/activeadmin/activeadmin/pull/5044 315 | [#5046]: https://github.com/activeadmin/activeadmin/pull/5046 316 | [#5052]: https://github.com/activeadmin/activeadmin/pull/5052 317 | [#5060]: https://github.com/activeadmin/activeadmin/pull/5060 318 | [#5069]: https://github.com/activeadmin/activeadmin/pull/5069 319 | [#5081]: https://github.com/activeadmin/activeadmin/pull/5081 320 | [#5088]: https://github.com/activeadmin/activeadmin/pull/5088 321 | [#5093]: https://github.com/activeadmin/activeadmin/pull/5093 322 | [#5104]: https://github.com/activeadmin/activeadmin/pull/5104 323 | [#5119]: https://github.com/activeadmin/activeadmin/pull/5119 324 | [#5120]: https://github.com/activeadmin/activeadmin/pull/5120 325 | [#5125]: https://github.com/activeadmin/activeadmin/pull/5125 326 | [#5137]: https://github.com/activeadmin/activeadmin/pull/5137 327 | [#5143]: https://github.com/activeadmin/activeadmin/pull/5143 328 | [#5157]: https://github.com/activeadmin/activeadmin/pull/5157 329 | [#5167]: https://github.com/activeadmin/activeadmin/pull/5167 330 | [#5180]: https://github.com/activeadmin/activeadmin/pull/5180 331 | [#5187]: https://github.com/activeadmin/activeadmin/pull/5187 332 | [#5194]: https://github.com/activeadmin/activeadmin/pull/5194 333 | [#5208]: https://github.com/activeadmin/activeadmin/pull/5208 334 | [#5210]: https://github.com/activeadmin/activeadmin/pull/5210 335 | [#5223]: https://github.com/activeadmin/activeadmin/pull/5223 336 | [#5238]: https://github.com/activeadmin/activeadmin/pull/5238 337 | [#5240]: https://github.com/activeadmin/activeadmin/pull/5240 338 | [#5251]: https://github.com/activeadmin/activeadmin/pull/5251 339 | [#5253]: https://github.com/activeadmin/activeadmin/pull/5253 340 | [#5266]: https://github.com/activeadmin/activeadmin/pull/5266 341 | [#5272]: https://github.com/activeadmin/activeadmin/pull/5272 342 | [#5275]: https://github.com/activeadmin/activeadmin/pull/5275 343 | [#5284]: https://github.com/activeadmin/activeadmin/pull/5284 344 | [#5295]: https://github.com/activeadmin/activeadmin/pull/5295 345 | [#5299]: https://github.com/activeadmin/activeadmin/pull/5299 346 | [#5320]: https://github.com/activeadmin/activeadmin/pull/5320 347 | [#5324]: https://github.com/activeadmin/activeadmin/pull/5324 348 | [#5330]: https://github.com/activeadmin/activeadmin/pull/5330 349 | [#5334]: https://github.com/activeadmin/activeadmin/pull/5334 350 | [#5336]: https://github.com/activeadmin/activeadmin/pull/5336 351 | [#5341]: https://github.com/activeadmin/activeadmin/pull/5341 352 | [#5343]: https://github.com/activeadmin/activeadmin/pull/5343 353 | [#5357]: https://github.com/activeadmin/activeadmin/pull/5357 354 | [#5359]: https://github.com/activeadmin/activeadmin/pull/5359 355 | [#5368]: https://github.com/activeadmin/activeadmin/pull/5368 356 | [#5375]: https://github.com/activeadmin/activeadmin/pull/5375 357 | [#5377]: https://github.com/activeadmin/activeadmin/pull/5377 358 | [#5399]: https://github.com/activeadmin/activeadmin/pull/5399 359 | [#5401]: https://github.com/activeadmin/activeadmin/pull/5401 360 | [#5408]: https://github.com/activeadmin/activeadmin/pull/5408 361 | [#5413]: https://github.com/activeadmin/activeadmin/pull/5413 362 | [#5433]: https://github.com/activeadmin/activeadmin/pull/5433 363 | [#5446]: https://github.com/activeadmin/activeadmin/pull/5446 364 | [#5448]: https://github.com/activeadmin/activeadmin/pull/5448 365 | [#5453]: https://github.com/activeadmin/activeadmin/pull/5453 366 | [#5458]: https://github.com/activeadmin/activeadmin/pull/5458 367 | [#5461]: https://github.com/activeadmin/activeadmin/pull/5461 368 | [#5464]: https://github.com/activeadmin/activeadmin/pull/5464 369 | [#5486]: https://github.com/activeadmin/activeadmin/pull/5486 370 | [#5501]: https://github.com/activeadmin/activeadmin/pull/5501 371 | [#5517]: https://github.com/activeadmin/activeadmin/pull/5517 372 | [#5537]: https://github.com/activeadmin/activeadmin/pull/5537 373 | [#5583]: https://github.com/activeadmin/activeadmin/pull/5583 374 | 375 | [@5t111111]: https://github.com/5t111111 376 | [@aarek]: https://github.com/aarek 377 | [@ajw725]: https://github.com/ajw725 378 | [@alex-bogomolov]: https://github.com/alex-bogomolov 379 | [@andreslemik]: https://github.com/andreslemik 380 | [@blocknotes]: https://github.com/blocknotes 381 | [@bolshakov]: https://github.com/bolshakov 382 | [@chancancode]: https://github.com/chancancode 383 | [@chumakoff]: https://github.com/chumakoff 384 | [@craigmcnamara]: https://github.com/craigmcnamara 385 | [@DanielHeath]: https://github.com/DanielHeath 386 | [@deivid-rodriguez]: https://github.com/deivid-rodriguez 387 | [@dennisvdvliet]: https://github.com/dennisvdvliet 388 | [@dhyegofernando]: https://github.com/dhyegofernando 389 | [@dmitry]: https://github.com/dmitry 390 | [@drn]: https://github.com/drn 391 | [@eikes]: https://github.com/eikes 392 | [@f1sherman]: https://github.com/f1sherman 393 | [@faucct]: https://github.com/faucct 394 | [@Fivell]: https://github.com/Fivell 395 | [@glebtv]: https://github.com/glebtv 396 | [@gonzedge]: https://github.com/gonzedge 397 | [@innparusu95]: https://github.com/innparusu95 398 | [@jasl]: https://github.com/jasl 399 | [@javierjulio]: https://github.com/javierjulio 400 | [@jawa]: https://github.com/jawa 401 | [@JiiHu]: https://github.com/JiiHu 402 | [@johnnyshields]: https://github.com/johnnyshields 403 | [@kjeldahl]: https://github.com/kjeldahl 404 | [@kobeumut]: https://github.com/kobeumut 405 | [@leio10]: https://github.com/leio10 406 | [@markstory]: https://github.com/markstory 407 | [@mauriciopasquier]: https://github.com/mauriciopasquier 408 | [@mconiglio]: https://github.com/mconiglio 409 | [@Nguyenanh]: https://github.com/Nguyenanh 410 | [@PChambino]: https://github.com/PChambino 411 | [@potatosalad]: https://github.com/potatosalad 412 | [@pranas]: https://github.com/pranas 413 | [@renotocn]: https://github.com/renotocn 414 | [@RobinvanderVliet]: https://github.com/RobinvanderVliet 415 | [@rogerkk]: https://github.com/rogerkk 416 | [@seanlinsley]: https://github.com/seanlinsley 417 | [@ShallmentMo]: https://github.com/ShallmentMo 418 | [@shekibobo]: https://github.com/shekibobo 419 | [@shouya]: https://github.com/shouya 420 | [@stefsava]: https://github.com/stefsava 421 | [@tiagotex]: https://github.com/tiagotex 422 | [@timoschilling]: https://github.com/timoschilling 423 | [@TimPetricola]: https://github.com/TimPetricola 424 | [@varyonic]: https://github.com/varyonic 425 | [@wasifhossain]: https://github.com/wasifhossain 426 | [@Wowu]: https://github.com/Wowu 427 | [@wspurgin]: https://github.com/wspurgin 428 | [@zorab47]: https://github.com/zorab47 429 | [@chrp]: https://github.com/chrp 430 | -------------------------------------------------------------------------------- /test/fixtures/changelog/rake.rdoc: -------------------------------------------------------------------------------- 1 | === 10.4.2 / 2014-12-02 2 | 3 | Bug fixes: 4 | 5 | * Rake no longer edits ARGV. This allows you to re-exec rake from a rake 6 | task. Pull requset #9 by Matt Palmer. 7 | * Documented how Rake::DSL#desc handles sentences in task descriptions. 8 | Issue #7 by Raza Sayed. 9 | * Fixed test error on 1.9.3 with legacy RubyGems. Issue #8 by Matt Palmer. 10 | * Deleted duplicated History entry. Pull request #10 by Yuji Yamamoto. 11 | 12 | === 10.4.1 / 2014-12-01 13 | 14 | Bug fixes: 15 | 16 | * Reverted fix for #277 as it caused numerous issues for rake users. 17 | rails/spring issue #366 by Gustavo Dutra. 18 | 19 | === 10.4.0 / 2014-11-22 20 | 21 | Enhancements: 22 | 23 | * Upgraded to minitest 5. Pull request #292 by Teo Ljungberg. 24 | * Added support for Pathname in rake tasks. Pull request #271 by Randy 25 | Coulman. 26 | * Rake now ignores falsy dependencies which allows for easier programmatic 27 | creation of tasks. Pull request #273 by Manav. 28 | * Rake no longer edits ARGV. This allows you to re-exec rake from a rake 29 | task. Issue #277 by Matt Palmer. 30 | * Etc.nprocessors is used for counting the number of CPUs. 31 | 32 | Bug fixes: 33 | 34 | * Updated rake manpage. Issue #283 by Nathan Long, pull request #291 by 35 | skittleys. 36 | * Add Rake::LATE to allow rebuilding of files that depend on deleted files. 37 | Bug #286, pull request #287 by David Grayson. 38 | * Fix relinking of files when repackaging. Bug #276 by Muenze. 39 | * Fixed some typos. Pull request #280 by Jed Northridge. 40 | * Try counting CPUs via cpuinfo if host_os was not matched. Pull request 41 | #282 by Edouard B. 42 | 43 | === 10.3.2 / 2014-05-15 44 | 45 | Bug fixes: 46 | 47 | * Rake no longer infinitely loops when showing exception causes that refer to 48 | each other. Bug #272 by Chris Bandy. 49 | * Fixed documentation typos. Bug #275 by Jake Worth. 50 | 51 | === 10.3.1 / 2014-04-17 52 | 53 | Bug fixes: 54 | 55 | * Really stop reporting an error when cleaning already-deleted files. Pull 56 | request #269 by Randy Coulman 57 | * Fixed infinite loop when cleaning already-deleted files on windows. 58 | 59 | === 10.3 / 2014-04-15 60 | 61 | Enhancements: 62 | 63 | * Added --build-all option to rake which treats all file prerequisites as 64 | out-of-date. Pull request #254 by Andrew Gilbert. 65 | * Added Rake::NameSpace#scope. Issue #263 by Jon San Miguel. 66 | 67 | Bug fixes: 68 | 69 | * Suppress org.jruby package files in rake error messages for JRuby users. 70 | Issue #213 by Charles Nutter. 71 | * Fixed typo, removed extra "h". Pull request #267 by Hsing-Hui Hsu. 72 | * Rake no longer reports an error when cleaning already-deleted files. Pull 73 | request #266 by Randy Coulman. 74 | * Consume stderr while determining CPU count to avoid hang. Issue #268 by 75 | Albert Sun. 76 | 77 | === 10.2.2 / 2014-03-27 78 | 79 | Bug fixes: 80 | 81 | * Restored Ruby 1.8.7 compatibility 82 | 83 | === 10.2.1 / 2014-03-25 84 | 85 | Bug fixes: 86 | 87 | * File tasks including a ':' are now top-level tasks again. Issue #262 by 88 | Josh Holtrop. 89 | * Use sysctl for CPU count for all BSDs. Pull request #261 by Joshua Stein. 90 | * Fixed CPU detection for unknown platforms. 91 | 92 | === 10.2.0 / 2014-03-24 93 | 94 | Enhancements: 95 | 96 | * Rake now requires Ruby 1.9 or newer. For me, this is a breaking change, but 97 | it seems that Jim planned to release it with Rake 10.2. See also pull 98 | request #247 by Philip Arndt. 99 | * Rake now allows you to declare tasks under a namespace like: 100 | 101 | task 'a:b' do ... end 102 | 103 | Pull request #232 by Judson Lester. 104 | * Task#source defaults to the first prerequisite in non-rule tasks. Pull 105 | request #215 by Avdi Grimm. 106 | * Rake now automatically rebuilds and reloads imported files. Pull request 107 | #209 by Randy Coulman. 108 | * The rake task arguments can contain escaped commas. Pull request #214 by 109 | Filip Hrbek. 110 | * Rake now prints the exception class on errors. Patch #251 by David Cornu. 111 | 112 | Bug fixes: 113 | 114 | * Fixed typos. Pull request #256 by Valera Rozuvan, #250 via Jake Worth, #260 115 | by Zachary Scott. 116 | * Fixed documentation for calling tasks with arguments. Pull request #235 by 117 | John Varghese. 118 | * Clarified `rake -f` usage message. Pull request #252 by Marco Pfatschbacher. 119 | * Fixed a test failure on windows. Pull request #231 by Hiroshi Shirosaki. 120 | * Fixed corrupted rake.1.gz. Pull request #225 by Michel Boaventura. 121 | * Fixed bug in can_detect_signals? in test. Patch from #243 by Alexey 122 | Borzenkov. 123 | 124 | === 10.1.1 and earlier 125 | 126 | Additions to the old CHANGES file were not made consistently so some 127 | versions are missing from this file. These changes are usually described in 128 | the individual release notes files. 129 | 130 | === 0.9.3 131 | 132 | * The rake test loader now removes arguments it has processed. Issue #51 133 | * Rake::TaskArguments now responds to #values_at 134 | * RakeFileUtils.verbose_flag = nil silences output the same as 0.8.7 135 | * Rake tests are now directory-independent 136 | * Rake tests are no longer require flexmock 137 | * Commands constant is no longer polluting top level namespace. 138 | * Show only the interesting portion of the backtrace by default (James M. Lawrence). 139 | * Added --reduce-compat optiont to remove backward compatible DSL hacks (James M. Lawrence). 140 | * lib/rake/file_list.rb (Rake::FileList#egrep): there is no need to 141 | open files in binary mode. (NAKAMURA Usaku) 142 | 143 | === 0.9.2 144 | 145 | * Unknown 146 | 147 | === 0.9.1 148 | 149 | * Added deprecation warnings to the Rake DSL methods. 150 | 151 | === 0.9.0 152 | 153 | * *Incompatible* *change*: Rake DSL commands ('task', 'file', etc.) are 154 | no longer private methods in Object. If you need to call 'task :xzy' inside 155 | your class, include Rake::DSL into the class. The DSL is still available at 156 | the top level scope (via the top level object which extends Rake::DSL). 157 | 158 | * Rake now warns when the deprecated :needs syntax used. 159 | 160 | * Rake history is now UTF-8 encoded. 161 | 162 | * Rake now uses case-insensitive comparisons to find the Rakefile on Windows. 163 | Based on patch by Roger Pack. 164 | 165 | * Rake now requires (instead of loads) files in the test task. Patch by Cezary 166 | Baginski. 167 | 168 | * Fixed typos. Patches by Sean Scot August Moon and R.T. Lechow. 169 | 170 | * Rake now prints the Rakefile directory only when it's different from the 171 | current directory. Patch by Alex Chaffee. 172 | 173 | * Improved rakefile_location discovery on Windows. Patch by James Tucker. 174 | 175 | * Rake now recognizes "Windows Server" as a windows system. Patch by Matthias 176 | Lüdtke 177 | 178 | * Rake::RDocTask is deprecated. Use RDoc::Task from RDoc 2.4.2+ (require 179 | 'rdoc/task') 180 | 181 | * Rake::GemPackageTask is deprecated. Use Gem::PackageTask (require 182 | 'rubygems/package_task') 183 | 184 | * Rake now outputs various messages to $stderr instead of $stdout. 185 | 186 | * Rake no longer emits warnings for Config. Patch by Santiago Pastorino. 187 | 188 | * Split rake.rb into individual files. 189 | 190 | * Support for the --where (-W) flag for showing where a task is defined. 191 | 192 | * Fixed quoting in test task. 193 | (http://onestepback.org/redmine/issues/show/44, 194 | http://www.pivotaltracker.com/story/show/1223138) 195 | 196 | * Fixed the silent option parsing problem. 197 | (http://onestepback.org/redmine/issues/show/47) 198 | 199 | * Fixed :verbose=>false flag on sh and ruby commands. 200 | 201 | * Rake command line options may be given by default in a RAKEOPT 202 | environment variable. 203 | 204 | * Errors in Rake will now display the task invocation chain in effect 205 | at the time of the error. 206 | 207 | * Accepted change by warnickr to not expand test patterns in shell 208 | (allowing more files in the test suite). 209 | 210 | * Fixed that file tasks did not perform prereq lookups in scope 211 | (Redmine #57). 212 | 213 | === 0.8.7 214 | 215 | * Fixed EXEEXT for JRuby on windows. 216 | 217 | === 0.8.6 218 | 219 | * Minor fixes to the RDoc generation (removed dependency on darkfish 220 | and removed inline source option). 221 | 222 | * Now allow # comments to comment a task definition. 223 | 224 | === 0.8.5 225 | 226 | * Better support for the system command on Windows. 227 | 228 | === 0.8.4 229 | 230 | * Preserve case when locating rakefiles (patch from James 231 | M. Lawrence/quix) 232 | 233 | * Better support for windows paths in the test task (patch from Simon 234 | Chiang/bahuvrihi) 235 | 236 | * Windows system dir search order is now: HOME, HOMEDRIVE + HOMEPATH, 237 | APPDATA, USERPROFILE (patch from Luis Lavena) 238 | 239 | * MingGW is now recognized as a windows platform. (patch from Luis 240 | Lavena) 241 | 242 | * Numerous fixes to the windows test suite (patch from Luis Lavena). 243 | 244 | * Improved Rakefile case insensitivity testing (patch from Luis 245 | Lavena). 246 | 247 | * Fixed stray ARGV option problem that was interfering with 248 | Test::Unit::Runner. 249 | 250 | * Fixed default verbose mode (was accidently changed to false). 251 | 252 | * Removed reference to manage_gem to fix the warning produced by the 253 | gem package task. 254 | 255 | === 0.8.3 256 | 257 | * Enhanced the system directory detection in windows. We now check 258 | HOMEDRIVE/HOMEPATH and USERPROFILE if APPDATA isn't found. (Patch 259 | supplied by James Tucker). Rake no long aborts if it can't find the 260 | directory. 261 | 262 | * Added fix to handle ruby installations in directories with spaces in 263 | their name. 264 | 265 | === 0.8.2 266 | 267 | * Fixed bug in package task so that it will include the subdir 268 | directory in the package for testing. (Bug found by Adam Majer) 269 | 270 | * Added ENV var to rakefile to prevent OS X from including extended 271 | attribute junk in a tar file. (Bug found by Adam Majer) 272 | 273 | * Fixed filename dependency order bug in test_inspect_pending and 274 | test_to_s_pending. (Bug found by Adam Majer) 275 | 276 | * Fixed check for file utils options to make them immune to the 277 | symbol/string differences. (Patch supplied by Edwin Pratomo) 278 | 279 | * Fixed bug with rules involving multiple source (Patch supplied by 280 | Emanuel Indermühle) 281 | 282 | * Switched from getoptlong to optparse (patches supplied by Edwin 283 | Pratomo) 284 | 285 | * The -T option will now attempt to dynamically sense the size of the 286 | terminal. RAKE_COLUMNS will override any dynamic sensing. 287 | 288 | * FileList#clone and FileList#dup have better sematics w.r.t. taint 289 | and freeze. 290 | 291 | * Added ability clear prerequisites, and/or actions from an existing 292 | task. 293 | 294 | * Added the ability to reenable a task to be invoked a second time. 295 | 296 | * Changed RDoc test task to have no default template. This makes it 297 | easier for the tempate to pick up the template from the environment. 298 | 299 | * Changed from using Mutex to Monitor. Evidently Mutex causes thread 300 | join errors when Ruby is compiled with -disable-pthreads. (Patch 301 | supplied by Ittay Dror) 302 | 303 | * Fixed bug in makefile parser that had problems with extra spaces in 304 | file task names. (Patch supplied by Ittay Dror) 305 | 306 | * Added a performance patch for reading large makefile dependency 307 | files. (Patch supplied by Ittay Dror) 308 | 309 | * Default values for task arguments can easily be specified with the 310 | :with_defaults method. (Idea for default argument merging supplied 311 | by (Adam Q. Salter) 312 | 313 | * The -T output will only self-truncate if the output is a tty. 314 | However, if RAKE_COLUMNS is explicitly set, it will be honored in 315 | any case. (Patch provided by Gavin Stark). 316 | 317 | * Numerous fixes for running under windows. A big thanks to Bheeshmar 318 | Redheendran for spending a good part of the afternoon at the 319 | Lonestar Ruby Conference to help me work out these issues. 320 | 321 | === 0.8.1 322 | 323 | * Removed requires on parsedate.rb (in Ftptools) 324 | * Removed ftools from rake.rb. Made it options in sys.rb 325 | 326 | === 0.8.0 327 | 328 | * Added task parameters (e.g. "rake build[version7]") 329 | * Made task parameters passable to prerequisites. 330 | * Comments are limited to 80 columns or so (suggested by Jamis Buck). 331 | * Added -D to display full comments (suggested by Jamis Buck). 332 | * The rake program will set the status value used in any explicit 333 | exit(n) calls. (patch provided by Stephen Touset) 334 | * Fixed error in functional tests that were not including session (and 335 | silently skipping the functionl tests. 336 | * Removed --usage and make -h the same as -H. 337 | * Make a prettier inspect for tasks. 338 | 339 | === 0.7.3 340 | 341 | * Added existing and existing! methods to FileList 342 | * FileLists now claim to be Arrays (via is_a?) to get better support 343 | from the FileUtil module. 344 | * Added init and top_level for custom rake applications. 345 | 346 | === 0.7.2 347 | 348 | * Error messages are now send to stderr rather than stdout (from 349 | Payton Quackenbush). 350 | * Better error handling on invalid command line arguments (from Payton 351 | Quackenbush). 352 | * Added rcov task and updated unit testing for better code coverage. 353 | * Fixed some bugs where the application object was going to the global 354 | appliation instead of using its own data. 355 | * Added square and curly bracket patterns to FileList#include (Tilman 356 | Sauerbeck). 357 | * Added plain filename support to rule dependents (suggested by Nobu 358 | Nakada). 359 | * Added pathmap support to rule dependents. 360 | * Added a 'tasks' method to a namespace to get a list of tasks 361 | associated with the namespace. 362 | * Fixed the method name leak from FileUtils (bug found by Glenn 363 | Vanderburg). 364 | * Added rake_extension to handle detection of extension collisions. 365 | * Added test for noop, bad_option and verbose flags to sh command. 366 | * Removed dependency on internal fu_xxx functions from FileUtils. 367 | * Added a 'shame' task to the Rakefile. 368 | * Added tar_command and zip_command options to the Package task. 369 | * Added a description to the gem task in GemPackageTask. 370 | * Fixed a bug when rules have multiple prerequisites (patch by Joel 371 | VanderWerf) 372 | * Added a protected 'require "rubygems"' to test/test_application to 373 | unbreak cruisecontrol.rb. 374 | * Added the handful of RakeFileUtils to the private method as well. 375 | * Added block based exclusion. 376 | * The clean task will no longer delete 'core' if it is a directory. 377 | * Removed rake_dup. Now we just simply rescue a bad dup. 378 | * Refactored the FileList reject logic to remove duplication. 379 | * Removed if __FILE__ at the end of the rake.rb file. 380 | 381 | === 0.7.1 382 | 383 | * Added optional filter parameter to the --tasks command line option. 384 | * Added flatten to allow rule transform procs to return lists of 385 | prereqs (Joel VanderWerf provided patch). 386 | * Added pathmap to String and FileList. 387 | * The -r option will now load .rake files (but a straight require 388 | doesn't yet). NOTE: This is experimental ... it may be 389 | discontinued. 390 | * The -f option without a value will disable the search for a 391 | Rakefile. The assumption is that the -r files are adequate. 392 | * Fixed the safe_ln function to fall back to cp in more error 393 | scenarios. 394 | 395 | === 0.7.0 396 | 397 | * Added Rake.original_dir to return the original starting directory of 398 | the rake application. 399 | * Added safe_ln support for openAFS (from Ludvig Omholt). 400 | * Added --trace reminder on short exception messages (David Heinemeier 401 | Hansson suggestion). 402 | * Added multitask declaration that executes prerequisites in 403 | parallel. (Doug Young providied an initial implementation). 404 | * Fixed missing_const hack to be compatible with Rails. (Jamis Buck 405 | supplied test case). 406 | * Made the RDoc task default to internal (in-process) RDoc formatting. 407 | The old behavior is still available by setting the +external+ flag 408 | to true. 409 | * Rakefiles are now loaded with the expanded path to prevent 410 | accidental polution from the Ruby load path. 411 | * The +namespace+ command now returns a NameSpace object that can be 412 | used to lookup tasks defined in that namespace. This allows for 413 | better anonymous namespace behavior. 414 | * Task objects my now be used in prerequisite lists directly. 415 | 416 | === 0.6.1 417 | 418 | * Rebuilt 0.6.0 gem without signing. 419 | 420 | === 0.6.0 421 | 422 | * Fixed file creation bug in the unit tests (caused infinite loop on 423 | windows). 424 | * Fixed bug where session based functional tests were run under 425 | windows. 426 | * Fixed bug in directory tasks so that updating a directory will not 427 | retrigger file tasks depending on the directory (see 428 | FileCreationTask and EarlyTime). 429 | * Added egrep to FileList 430 | * ruby command now runs same ruby version as rake. 431 | * Added investigation to task object. (suggested by Martin Fowler) 432 | * Added ruby_opts to the test task to allow arbitrary ruby options to 433 | be passed to the test script. (Greg Fast) 434 | * Fixed the test loader to ignore options. (Greg Fast) 435 | * Moved Task, FileTask, FileCreationTask and RakeApp into the Rake 436 | module namespace. Old style namespace behavior can be invoked via 437 | the --classic-namespace option. (requested by Kelly Felkins). 438 | * GemTask is now sensitive to the gem platform (Masao Mutoh). 439 | * A non-existing file prerequisite will no longer cause an exception 440 | (Philipp Neubeck). 441 | * Multiple prerequisites on Rake rules now allowed (initial patch 442 | supplied by Stuart Jansen). 443 | 444 | === 0.5.4 445 | 446 | * Added double quotes to the test runner. 447 | * Added .svn to default ignore list. 448 | * Updated FileList#include to support nested arrays and filelists. 449 | 450 | === 0.5.3 451 | 452 | * Added support for importing Rakefile and other dependencies. 453 | * Fixed bug so that now rules can chain off of existing tasks as well 454 | as existing files. 455 | * Fixed verbose flag bug in the testing task. Shortened some failure 456 | messages. 457 | * Make FileUtils methods private at the top level module to avoid 458 | accidental method leaking into other objects. 459 | * Added test loader option to test task. "testrb" is no longer the 460 | default test loader. It is now eating syntax errors that should 461 | halt the unit tests. 462 | * Revamped FileList so that it works more like and array (addressed 463 | flatten bug). Added many tests around file list. 464 | * Added +ext+ method to both String and FileList. 465 | 466 | === 0.5.0 467 | 468 | * Fixed documentation that was lacking the Rake module name (Tilman 469 | Sauerbeck). 470 | * Added tar.gz and tar.bz2 support to package task (Tilman Sauerbeck). 471 | * Recursive rules are now supported (Tilman Sauerbeck). 472 | * Added warning option for the Test Task (requested by Eric Hodel). 473 | * The jamis rdoc template is only used if it exists. 474 | * Added fix for Ruby 1.8.2 test/unit and rails problem. 475 | * Added contributed rake man file (Jani Monoses). 476 | * Added Brian Candler's fix for problems in --trace and --dry-run 477 | mode. 478 | 479 | === 0.4.15 480 | 481 | * Fixed a bug that prevented the TESTOPTS flag from working with the 482 | revised for 1.8.2 test task. 483 | * Updated the docs on --trace to indicate that it also enables a full 484 | backtrace on errors. 485 | 486 | === 0.4.14 487 | 488 | * Modified the TestTask to workaround the Ruby 1.8.2 change in 489 | autoexecuting unit tests. 490 | 491 | === 0.4.13 492 | 493 | * Fixed the dry-run flag so it is operating again. 494 | * Multiple arguments to sh and ruby commands will not be interpreted 495 | by the shell (patch provided by Jonathan Paisley). 496 | 497 | === 0.4.12 498 | 499 | * Added --silent (-s) to suppress the (in directory) rake message. 500 | 501 | === 0.4.11 502 | 503 | * Changed the "don't know how to rake" message (finally) 504 | * Changes references to a literal "Rakefile" to reference the global 505 | variable $rakefile (which contains the actual name of the rakefile). 506 | 507 | === 0.4.10 508 | 509 | * Added block support to the "sh" command, allowing users to take 510 | special actions on the result of the system call. E.g. 511 | 512 | sh "shell_command" do |ok, res| 513 | puts "Program returned #{res.exitstatus}" if ! ok 514 | end 515 | 516 | === 0.4.9 517 | 518 | * Switched to Jamis Buck's RDoc template. 519 | * Removed autorequire from Rake's gem spec. This prevents the Rake 520 | libraries from loading while using rails. 521 | 522 | === 0.4.8 523 | 524 | * Added support for .rb versions of Rakefile. 525 | * Removed \\\n's from test task. 526 | * Fixed Ruby 1.9 compatibility issue with FileList. 527 | 528 | === 0.4.7 529 | 530 | * Fixed problem in FileList that caused Ruby 1.9 to go into infinite 531 | recursion. Since to_a was removed from Object, it does not need to 532 | added back into the list of methods to rewrite in FileList. (Thanks 533 | to Kent Sibilev for pointing this out). 534 | 535 | === 0.4.6 536 | * Removed test version of ln in FileUtils that prevented safe_ln from 537 | using ln. 538 | 539 | === 0.4.5 540 | * Upgraded comments in TestTask. 541 | * FileList to_s and inspect now automatically resolve pending changes. 542 | * FileList#exclude properly returns the FileList. 543 | 544 | === 0.4.4 545 | * Fixed initialization problem with @comment. 546 | * Now using multi -r technique in TestTask. Switch Rakefile back to 547 | using the built-in test task macros because the rake runtime is no 548 | longer needed. 549 | * Added 'TEST=filename' and 'TESTOPTS=options' to the Test Task 550 | macros. 551 | * Allow a +test_files+ attribute in test tasks. This allows more 552 | flexibility in specifying test files. 553 | 554 | === 0.4.3 555 | * Fixed Comment leakage. 556 | 557 | === 0.4.2 558 | * Added safe_ln that falls back to a copy if a file link is not supported. 559 | * Package builder now uses safe_ln. 560 | 561 | === 0.4.1 562 | * Task comments are now additive, combined with "/". 563 | * Works with (soon to be released) rubygems 0.6.2 (or 0.7.0) 564 | 565 | === 0.4.0 566 | * FileList now uses deferred loading. The file system is not searched 567 | until the first call that needs the file names. 568 | * VAR=VALUE options are now accepted on the command line and are 569 | treated like environment variables. The values may be tested in a 570 | Rakefile by referencing ENV['VAR']. 571 | * File.mtime is now used (instead of File.new().mtime). 572 | 573 | === 0.3.2.x 574 | 575 | * Removed some hidden dependencies on rubygems. Tests now will test 576 | gems only if they are installed. 577 | * Removed Sys from some example files. I believe that is that last 578 | reference to Sys outside of the contrib area. 579 | * Updated all copyright notices to include 2004. 580 | 581 | === 0.3.2 582 | 583 | * GEM Installation now works with the application stub. 584 | 585 | === 0.3.1 586 | 587 | * FileLists now automatically ignore CVS, .bak, ! 588 | * GEM Installation now works. 589 | 590 | === 0.3.0 591 | 592 | Promoted 0.2.10. 593 | 594 | === 0.2.10 595 | General 596 | 597 | * Added title to Rake's rdocs 598 | * Contrib packages are no longer included in the documentation. 599 | 600 | RDoc Issues 601 | 602 | * Removed default for the '--main' option 603 | * Fixed rendering of the rdoc options 604 | * Fixed clean/clobber confusion with rerdoc 605 | * 'title' attribute added 606 | 607 | Package Task Library Issues 608 | 609 | * Version (or explicit :noversion) is required. 610 | * +package_file+ attribute is now writable 611 | 612 | FileList Issues 613 | 614 | * Dropped bang version of exclude. Now using ant-like include/exclude semantics. 615 | * Enabled the "yield self" idiom in FileList#initialize. 616 | 617 | === 0.2.9 618 | 619 | This version contains numerous changes as the RubyConf.new(2003) 620 | presentation was being prepared. The changes include: 621 | 622 | * The monolithic rubyapp task library is in the process of being 623 | dropped in favor of lighter weight task libraries. 624 | 625 | === 0.2.7 626 | 627 | * Added "desc" for task descriptions. 628 | * -T will now display tasks with descriptions. 629 | * -P will display tasks and prerequisites. 630 | * Dropped the Sys module in favor of the 1.8.x FileUtils module. Sys 631 | is still supported in the contrib area. 632 | 633 | === 0.2.6 634 | 635 | * Moved to RubyForge 636 | 637 | === 0.2.5 638 | 639 | * Switched to standard ruby app builder. 640 | * Added no_match option to file matcher. 641 | 642 | === 0.2.4 643 | 644 | * Fixed indir, which neglected to actually change directories. 645 | 646 | === 0.2.3 647 | 648 | * Added rake module for a help target 649 | * Added 'for_files' to Sys 650 | * Added a $rakefile constant 651 | * Added test for selecting proper rule with multiple targets. 652 | --------------------------------------------------------------------------------