apt_stage_artifacts 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +152 -0
- data/CHANGELOG.md +13 -0
- data/CODEOWNERS +3 -0
- data/DEVELOPMENT.md +18 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +13 -0
- data/README.md +25 -0
- data/Rakefile +32 -0
- data/apt_stage_artifacts.gemspec +37 -0
- data/bin/console +18 -0
- data/bin/setup +8 -0
- data/exe/apt-add-to-freight-library +5 -0
- data/exe/apt-stage-artifacts +5 -0
- data/exe/apt-stage-from-tarball +5 -0
- data/exe/apt-update-freight-cache +5 -0
- data/lib/apt_add_to_freight_library.rb +121 -0
- data/lib/apt_stage_artifacts.rb +188 -0
- data/lib/apt_stage_from_tarball.rb +110 -0
- data/lib/apt_update_freight_cache.rb +102 -0
- data/lib/mixins/logging.rb +29 -0
- data/lib/version.rb +3 -0
- metadata +185 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 24c10c67846c819b0174ac0b94f2a4b7836e73589969335c1fb4b6a2779e59bc
|
4
|
+
data.tar.gz: 47be9199cdabcc1bb1f242f6cd4e1aa8bea968d3ed83bc215e17c67ebe8d3f2c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 421d5a2a39379edddffa17bba6925c328d8f2a51d3af858743b771729b337ed74a9d4ce8c48a51798a6371f1b477fb16ab38833966339fe2ac6978650e0a8d4a
|
7
|
+
data.tar.gz: 585ec2d56f0959a19cb83fad46d5934265c1eaa1dce02b89155ada6a6d507dd3ab064e8a7447cffc5be3ea5384b4e9354331fdab1faf146a28a31e85c6fedb69
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
---
|
2
|
+
|
3
|
+
require: rubocop-rake
|
4
|
+
|
5
|
+
AllCops:
|
6
|
+
Exclude:
|
7
|
+
- Rakefile
|
8
|
+
- Gemfile
|
9
|
+
- bin/*
|
10
|
+
- spec/**/*.rb
|
11
|
+
- templates/*
|
12
|
+
|
13
|
+
Gemspec/DateAssignment:
|
14
|
+
Enabled: true
|
15
|
+
|
16
|
+
Layout/FirstArrayElementIndentation:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Layout/MultilineMethodCallIndentation:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Layout/SpaceBeforeBrackets:
|
23
|
+
Enabled: true
|
24
|
+
|
25
|
+
Lint/AmbiguousAssignment:
|
26
|
+
Enabled: true
|
27
|
+
|
28
|
+
Lint/DeprecatedConstants:
|
29
|
+
Enabled: true
|
30
|
+
|
31
|
+
Lint/DuplicateBranch:
|
32
|
+
Enabled: true
|
33
|
+
|
34
|
+
Lint/DuplicateRegexpCharacterClassElement:
|
35
|
+
Enabled: true
|
36
|
+
|
37
|
+
Lint/EmptyBlock:
|
38
|
+
Enabled: true
|
39
|
+
|
40
|
+
Lint/EmptyClass:
|
41
|
+
Enabled: true
|
42
|
+
|
43
|
+
Lint/LambdaWithoutLiteralBlock:
|
44
|
+
Enabled: true
|
45
|
+
|
46
|
+
Lint/NoReturnInBeginEndBlocks:
|
47
|
+
Enabled: true
|
48
|
+
|
49
|
+
Lint/NumberedParameterAssignment:
|
50
|
+
Enabled: true
|
51
|
+
|
52
|
+
Lint/OrAssignmentToConstant:
|
53
|
+
Enabled: true
|
54
|
+
|
55
|
+
Lint/RedundantDirGlobSort:
|
56
|
+
Enabled: true
|
57
|
+
|
58
|
+
Lint/SymbolConversion:
|
59
|
+
Enabled: true
|
60
|
+
|
61
|
+
Lint/ToEnumArguments:
|
62
|
+
Enabled: true
|
63
|
+
|
64
|
+
Lint/TripleQuotes:
|
65
|
+
Enabled: true
|
66
|
+
|
67
|
+
Lint/UnexpectedBlockArity:
|
68
|
+
Enabled: true
|
69
|
+
|
70
|
+
Lint/UnmodifiedReduceAccumulator:
|
71
|
+
Enabled: true
|
72
|
+
|
73
|
+
Metrics/AbcSize:
|
74
|
+
Enabled: false
|
75
|
+
|
76
|
+
Metrics/ClassLength:
|
77
|
+
Enabled: false
|
78
|
+
|
79
|
+
Metrics/CyclomaticComplexity:
|
80
|
+
Enabled: false
|
81
|
+
|
82
|
+
Metrics/MethodLength:
|
83
|
+
Enabled: false
|
84
|
+
|
85
|
+
Metrics/ModuleLength:
|
86
|
+
Enabled: false
|
87
|
+
|
88
|
+
Metrics/PerceivedComplexity:
|
89
|
+
Enabled: false
|
90
|
+
|
91
|
+
Style/ArgumentsForwarding:
|
92
|
+
Enabled: true
|
93
|
+
|
94
|
+
Style/CollectionCompact:
|
95
|
+
Enabled: true
|
96
|
+
|
97
|
+
Style/DocumentDynamicEvalDefinition:
|
98
|
+
Enabled: true
|
99
|
+
|
100
|
+
Style/Documentation:
|
101
|
+
Enabled: false
|
102
|
+
|
103
|
+
Style/EachWithObject:
|
104
|
+
Enabled: false
|
105
|
+
|
106
|
+
Style/EndlessMethod:
|
107
|
+
Enabled: true
|
108
|
+
|
109
|
+
Style/FormatString:
|
110
|
+
Enabled: false
|
111
|
+
|
112
|
+
Style/FormatStringToken:
|
113
|
+
Enabled: false
|
114
|
+
|
115
|
+
Style/FrozenStringLiteralComment:
|
116
|
+
Enabled: false
|
117
|
+
|
118
|
+
Style/HashConversion:
|
119
|
+
Enabled: true
|
120
|
+
|
121
|
+
Style/HashExcept:
|
122
|
+
Enabled: true
|
123
|
+
|
124
|
+
Style/IfUnlessModifier:
|
125
|
+
Enabled: false
|
126
|
+
|
127
|
+
Style/IfWithBooleanLiteralBranches:
|
128
|
+
Enabled: true
|
129
|
+
|
130
|
+
Style/MutableConstant:
|
131
|
+
Enabled: false
|
132
|
+
|
133
|
+
Style/NegatedIfElseCondition:
|
134
|
+
Enabled: true
|
135
|
+
|
136
|
+
Style/NilLambda:
|
137
|
+
Enabled: true
|
138
|
+
|
139
|
+
Style/RedundantArgument:
|
140
|
+
Enabled: true
|
141
|
+
|
142
|
+
Style/RedundantReturn:
|
143
|
+
Enabled: false
|
144
|
+
|
145
|
+
Style/StringChars:
|
146
|
+
Enabled: true
|
147
|
+
|
148
|
+
Style/SwapValues:
|
149
|
+
Enabled: true
|
150
|
+
|
151
|
+
Style/CommandLiteral:
|
152
|
+
Enabled: false
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## [Unreleased]
|
9
|
+
|
10
|
+
## [0.4.0] - 2021-04-28
|
11
|
+
### Added
|
12
|
+
- Initial release
|
13
|
+
|
data/CODEOWNERS
ADDED
data/DEVELOPMENT.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Development
|
2
|
+
|
3
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
4
|
+
|
5
|
+
## Local Build
|
6
|
+
|
7
|
+
To create a local build of the gem: `bundle exec rake build`
|
8
|
+
|
9
|
+
## Local Install
|
10
|
+
|
11
|
+
To install this gem onto your local machine: `bundle exec rake install`.
|
12
|
+
|
13
|
+
## New Release
|
14
|
+
|
15
|
+
To release a new version:
|
16
|
+
|
17
|
+
- update the version number in `lib/version.rb`
|
18
|
+
- run `bundle exec rake release` This will create a git tag for the version, push git commits and tags, and push the `.gem` file to [Puppet Artifactory Rubygems Repo ](https://artifactory.delivery.puppetlabs.net/artifactory/webapp/#/artifacts/browse/tree/General/rubygems).
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2021 Puppet, Inc.
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# apt_stage_artifacts
|
2
|
+
|
3
|
+
apt_stage_artifacts is a Ruby gem for Puppet Release Engineering to deliver locally built .deb packages to our freight-based apt repository staging.
|
4
|
+
|
5
|
+
It only handles internal staging and not the final push to outside customers.
|
6
|
+
|
7
|
+
The gem provides command-line programs for doing the staging.
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
### apt-stage-artifacts
|
12
|
+
|
13
|
+
The main user script, `apt-stage-artifacts` expects the current directory to be a vanagon-style build where debian `.deb` files have been built into `output/deb`.
|
14
|
+
|
15
|
+
After consulting the [build-data](https://github.com/puppetlabs/build-data/blob/release/builder_data.yaml) repo for the name of the staging machine, it packs up the debian artifacts into a tarball and copies it there via scp.
|
16
|
+
|
17
|
+
It then invokes the remaining scripts on the staging machine to do the rest of the staging:
|
18
|
+
|
19
|
+
### apt-stage-from-tarball
|
20
|
+
|
21
|
+
`apt-stage-from-tarball` runs in the staging server. It unpacks the tarball created by `apt-stage-artifacts` and calls `apt-add-to-freight-library` on each of them. This adds each `.deb` file to the correct freight library (puppet6, puppet7, puppet7-nightly, etc.)
|
22
|
+
|
23
|
+
Once all .deb files have been added, `apt-stage-from-tarball` calls `apt-update-freight-cache`, which instructs freight to generate the actual APT repo (which freight calls a "cache"), including GPG signing of the resulting cache.
|
24
|
+
|
25
|
+
When completed, the resulting "caches" are signed, functional APT repos which can sync'd to the outside world.
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'yard'
|
4
|
+
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
YARD::Rake::YardocTask.new
|
7
|
+
|
8
|
+
task :build => :yard
|
9
|
+
task :default => :spec
|
10
|
+
|
11
|
+
desc 'Run rubocop'
|
12
|
+
task :rubocop do
|
13
|
+
sh 'rubocop || true'
|
14
|
+
end
|
15
|
+
|
16
|
+
task :clean do
|
17
|
+
sh 'rm -f pkg/*.gem'
|
18
|
+
end
|
19
|
+
|
20
|
+
task :devtest => [:clean, :build, :install] do
|
21
|
+
test_host = ENV['APT_STAGE_TEST_HOST'].to_s
|
22
|
+
if test_host.empty?
|
23
|
+
puts 'Error: the "APT_STAGE_TEST_HOST" environment variable is unset.'
|
24
|
+
puts 'Set it to the hostname where the test freight environment exists.'
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
|
28
|
+
sh "ssh #{test_host} rm -f ~/apt_stage_artifacts\*.gem"
|
29
|
+
sh "scp pkg/apt_stage_artifacts*.gem #{test_host}:~"
|
30
|
+
sh "ssh #{test_host} gem uninstall apt_stage_artifacts"
|
31
|
+
sh "ssh #{test_host} gem install apt_stage_artifacts\*.gem"
|
32
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative 'lib/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = 'apt_stage_artifacts'
|
5
|
+
spec.version = AptStageArtifacts::VERSION
|
6
|
+
spec.authors = ['Puppet Release Engineering']
|
7
|
+
spec.email = ['release@puppet.com']
|
8
|
+
|
9
|
+
spec.summary = 'Stages .deb artifacts to a remote freight repository'
|
10
|
+
spec.homepage = 'https://github.com/puppetlabs/apt_stage_artifacts'
|
11
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
|
12
|
+
|
13
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
14
|
+
|
15
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
16
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
17
|
+
spec.metadata['changelog_uri'] = File.join(spec.homepage, 'CHANGELOG.md')
|
18
|
+
|
19
|
+
# Specify which files should be added to the gem when it is released.
|
20
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
22
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
23
|
+
end
|
24
|
+
spec.bindir = 'exe'
|
25
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
|
+
spec.require_paths = ['lib']
|
27
|
+
|
28
|
+
spec.add_development_dependency 'pry', '~> 0.14'
|
29
|
+
spec.add_development_dependency 'pry-byebug', '~> 3.0'
|
30
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
31
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
32
|
+
spec.add_development_dependency 'rubocop-rake'
|
33
|
+
spec.add_development_dependency 'rubocop-rspec'
|
34
|
+
spec.add_development_dependency 'yard', '~> 0.9'
|
35
|
+
|
36
|
+
spec.add_runtime_dependency 'docopt'
|
37
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'apt_add_to_freight_library'
|
5
|
+
require 'apt_stage_artifacts'
|
6
|
+
require 'apt_stage_from_tarball'
|
7
|
+
require 'apt_update_freight_cache'
|
8
|
+
|
9
|
+
require 'irb'
|
10
|
+
|
11
|
+
puts %{Mininal startup options. Choose one:
|
12
|
+
irb> AptAddToFreightLibrary.new(Array.new)
|
13
|
+
irb> AptStageFromTarball.new(Array.new)
|
14
|
+
irb> AptUpdateFreightCache.new(Array.new)
|
15
|
+
irb> AptStageArtifacts.new(Array.new)
|
16
|
+
}
|
17
|
+
|
18
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'version'
|
2
|
+
require 'mixins/logging'
|
3
|
+
|
4
|
+
require 'English'
|
5
|
+
require 'docopt'
|
6
|
+
require 'open-uri'
|
7
|
+
require 'tmpdir'
|
8
|
+
|
9
|
+
## This is a wrapper for https://github.com/freight-team/freight, which creates APT repos
|
10
|
+
## from deb files.
|
11
|
+
##
|
12
|
+
## In our case, we maintain a set of debian repos, based on puppet version and a repo-type
|
13
|
+
## 'nightly', 'archive' and 'stable'.
|
14
|
+
##
|
15
|
+
## freight provides signing services, so this script needs to exist on a machine where GPG
|
16
|
+
## signing has been set up.
|
17
|
+
##
|
18
|
+
## Typical usage would be for a remote process to call this script with a list of .deb
|
19
|
+
## URLS:
|
20
|
+
##
|
21
|
+
## apt-add-to-freight-library --puppet-version=7 --repo-type=nightly --codename=stretch
|
22
|
+
## https://some-server.net/somepackage-a_0.19.2-1stretch_amd64.deb
|
23
|
+
## https://some-server.net/somepackage-b_0.19.2-1stretch_amd64.deb
|
24
|
+
##
|
25
|
+
## Alternately one coule scp a bunch of .deb files to the machine
|
26
|
+
## this is installed on then call this script with all the deb files as arguments. For example:
|
27
|
+
##
|
28
|
+
## apt-add-to-freight-library --puppet-version=7 --repo-type=nightly --codename=buster
|
29
|
+
## /tmp/xxtmpdir/somepackage-a_0.0.0-1buster_amd64.deb
|
30
|
+
## /tmp/xxtmpdir/somepackage-b_1.2.3-5buster_amd64.deb
|
31
|
+
## (etc.)
|
32
|
+
|
33
|
+
class AptAddToFreightLibrary
|
34
|
+
include Logging
|
35
|
+
|
36
|
+
FREIGHT_COMMAND = '/usr/bin/freight'
|
37
|
+
VALID_PUPPET_VERSIONS = %w[6 7 8]
|
38
|
+
VALID_REPO_TYPES = %w[archive nightly stable]
|
39
|
+
VALID_CODENAMES = %w[bionic jessie stretch buster bullseye bookwork focal xenial]
|
40
|
+
|
41
|
+
DOCUMENTATION = <<~DOCOPT
|
42
|
+
Adds debian .deb files to a freight library.
|
43
|
+
|
44
|
+
Usage:
|
45
|
+
apt-add-to-freight-library [--verbose] --puppet-version=VERSION --repo-type=REPO_TYPE --codename=DEBIAN_CODENAME <deb_file> ...
|
46
|
+
apt-add-to-freight-library --help
|
47
|
+
apt-add-to-freight-library --version
|
48
|
+
|
49
|
+
Options:
|
50
|
+
-p --puppet-version=VERSION Puppet version (Valid: #{VALID_PUPPET_VERSIONS.join(', ')})
|
51
|
+
-r --repo-type=REPO_TYPE Puppet debian repo type (Valid: #{VALID_REPO_TYPES.join(', ')})
|
52
|
+
-c --codename=DEBIAN_CODENAME Debian codename to deliver to (Valid: #{VALID_CODENAMES.join(', ')})
|
53
|
+
|
54
|
+
-v --verbose Be verbose
|
55
|
+
-h --help Show this help
|
56
|
+
--version Show version
|
57
|
+
DOCOPT
|
58
|
+
|
59
|
+
def initialize(argv)
|
60
|
+
@log_level = Logger::INFO
|
61
|
+
@user_options = parse_options(argv)
|
62
|
+
@verbose = ''
|
63
|
+
@verbose = '--verbose' if @user_options['--verbose']
|
64
|
+
|
65
|
+
@script_name = File.basename($PROGRAM_NAME)
|
66
|
+
@version_string = "#{@script_name} version #{AptStageArtifacts::VERSION}"
|
67
|
+
if @user_options['--version'] # rubocop:disable Style/GuardClause
|
68
|
+
puts @version_string
|
69
|
+
exit 0
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def parse_options(argv = nil)
|
74
|
+
Docopt.docopt(DOCUMENTATION, { argv: argv })
|
75
|
+
rescue Docopt::Exit => e
|
76
|
+
puts e.message
|
77
|
+
exit 1
|
78
|
+
end
|
79
|
+
|
80
|
+
def run
|
81
|
+
logger.info @version_string
|
82
|
+
@puppet_version = @user_options['--puppet-version']
|
83
|
+
fatal "Invalid Puppet version '#{@puppet_version}'" unless
|
84
|
+
VALID_PUPPET_VERSIONS.include? @puppet_version
|
85
|
+
|
86
|
+
@repo_type = @user_options['--repo-type']
|
87
|
+
fatal "Invalid repo type '#{@repo_type}'" unless VALID_REPO_TYPES.include? @repo_type
|
88
|
+
|
89
|
+
@codename = @user_options['--codename']
|
90
|
+
fatal "Invalid codename '#{@codename}'" unless VALID_CODENAMES.include? @codename
|
91
|
+
|
92
|
+
freight_config_file = "/etc/freight.conf.d/puppet_#{@puppet_version}_#{@repo_type}.conf"
|
93
|
+
fatal "Cannot read '#{freight_config_file} on #{`hostname`.chomp}." unless
|
94
|
+
File.readable?(freight_config_file)
|
95
|
+
|
96
|
+
logger.info "Using '#{freight_config_file}'"
|
97
|
+
deb_artifacts = @user_options['<deb_file>']
|
98
|
+
|
99
|
+
Dir.mktmpdir do |temporary_directory|
|
100
|
+
deb_artifacts.each do |artifact_path|
|
101
|
+
logger.info "Adding #{artifact_path} to puppet_#{@puppet_version}_#{@repo_type}"
|
102
|
+
deb_artifact_path = artifact_path
|
103
|
+
if deb_artifact_path.start_with?('https://', 'http://')
|
104
|
+
download_data = URI.parse(deb_artifact_path).open
|
105
|
+
download_path = File.join(temporary_directory, download_data.base_uri.to_s.split('/').last)
|
106
|
+
IO.copy_stream(download_data, download_path)
|
107
|
+
deb_artifact_path = download_path
|
108
|
+
end
|
109
|
+
|
110
|
+
freight_add_command = %W[
|
111
|
+
sudo --user=jenkins --set-home
|
112
|
+
#{FREIGHT_COMMAND} add #{@verbose} --conf="#{freight_config_file}"
|
113
|
+
#{deb_artifact_path} "apt/#{@codename}"
|
114
|
+
].join(' ')
|
115
|
+
|
116
|
+
%x(#{freight_add_command})
|
117
|
+
fatal "#{freight_add_command} failed." unless $CHILD_STATUS.success?
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require 'version'
|
2
|
+
require 'mixins/logging'
|
3
|
+
|
4
|
+
require 'English'
|
5
|
+
require 'docopt'
|
6
|
+
require 'fileutils'
|
7
|
+
require 'open-uri'
|
8
|
+
require 'tempfile'
|
9
|
+
require 'yaml'
|
10
|
+
|
11
|
+
class AptStageArtifacts
|
12
|
+
include Logging
|
13
|
+
|
14
|
+
DOCUMENTATION = <<~DOCOPT
|
15
|
+
Stages .deb artifacts into a freight library from a Vanagon or packaging directory.
|
16
|
+
|
17
|
+
Usage:
|
18
|
+
apt-stage-artifacts
|
19
|
+
apt-stage-artifacts <top_directory>
|
20
|
+
DOCOPT
|
21
|
+
|
22
|
+
def initialize(argv)
|
23
|
+
@script_name = File.basename($PROGRAM_NAME)
|
24
|
+
@log_level = Logger::INFO
|
25
|
+
@user_options = parse_options(argv)
|
26
|
+
@version_string = "#{@script_name} version #{AptStageArtifacts::VERSION}"
|
27
|
+
|
28
|
+
@artifacts_tarball_name = 'artifacts.tgz'
|
29
|
+
@local_tarball_path = File.join(Dir.pwd, @artifacts_tarball_name)
|
30
|
+
|
31
|
+
@builder_data_yaml = 'https://raw.githubusercontent.com/puppetlabs/build-data/release/builder_data.yaml'
|
32
|
+
|
33
|
+
@manifest_file_name = 'apt_stage.manifest'
|
34
|
+
@remote_staging_command = 'apt-stage-from-tarball'
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse_options(argv = nil)
|
38
|
+
Docopt.docopt(DOCUMENTATION, { argv: argv })
|
39
|
+
rescue Docopt::Exit => e
|
40
|
+
puts e.message
|
41
|
+
exit 1
|
42
|
+
end
|
43
|
+
|
44
|
+
def run
|
45
|
+
logger.info @version_string
|
46
|
+
parse_repo_type
|
47
|
+
load_builder_data_yaml
|
48
|
+
collect_artifacts
|
49
|
+
create_remote_staging_directory
|
50
|
+
generate_manifest
|
51
|
+
create_tarball
|
52
|
+
ship_tarball_to_staging_server
|
53
|
+
invoke_remote_staging
|
54
|
+
cleanup_tarball
|
55
|
+
logger.info 'Deb artifact staging successful.'
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
# Locate all the local debian artifacts to be added to the freight repo.
|
61
|
+
# For historical reasons, there is an implied format of:
|
62
|
+
# <top_directory>/<debian codename>/<artifact>.deb
|
63
|
+
#
|
64
|
+
# We rely on <debian codename> being in the first position below <top_directory>
|
65
|
+
# in order to properly classify the artifacts. This is definitely brittle.
|
66
|
+
def collect_artifacts
|
67
|
+
if !@user_options['<top_directory>'].to_s.empty?
|
68
|
+
@top_directory = @user_options['<top_directory>']
|
69
|
+
elsif File.directory?('./output/deb')
|
70
|
+
@top_directory = './output/deb'
|
71
|
+
elsif File.directory?('./pkg/deb')
|
72
|
+
@top_directory = './pkg/deb'
|
73
|
+
else
|
74
|
+
logger.error 'Cannot find .deb artifacts. Neither pkg/deb nor output/deb exist.'
|
75
|
+
exit 1
|
76
|
+
end
|
77
|
+
|
78
|
+
logger.info "Searching for .deb packages in #{@top_directory}"
|
79
|
+
Dir.chdir(@top_directory) do
|
80
|
+
@debian_artifacts = Dir['*/*.deb']
|
81
|
+
end
|
82
|
+
return unless @debian_artifacts.empty?
|
83
|
+
|
84
|
+
logger.error 'No .deb files found. Nothing to do.'
|
85
|
+
exit 0
|
86
|
+
end
|
87
|
+
|
88
|
+
# Create a working directory on the staging server that can then be used to deliver
|
89
|
+
# to freight repos.
|
90
|
+
def create_remote_staging_directory
|
91
|
+
@remote_staging_directory = %x(ssh #{@staging_server} /bin/mktemp --directory).chomp
|
92
|
+
fatal "/bin/mktemp --directory on #{@staging_server} failed." unless $CHILD_STATUS.success?
|
93
|
+
|
94
|
+
# We need to give jenkins read access to the remote_staging_directory
|
95
|
+
%x(ssh #{@staging_server} /bin/chmod 755 #{@remote_staging_directory})
|
96
|
+
unless $CHILD_STATUS.success?
|
97
|
+
fatal "/bin/chmod 755 #{@remote_staging_directory} on #{@staging_server} failed."
|
98
|
+
end
|
99
|
+
|
100
|
+
@remote_tarball_path = File.join(@remote_staging_directory, @artifacts_tarball_name)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Load details from the builder_data.yaml on github
|
104
|
+
# Keep only the bare necessities. Right now, that's just the staging server name.
|
105
|
+
def load_builder_data_yaml
|
106
|
+
yaml_content = URI.parse(@builder_data_yaml).open(&:read)
|
107
|
+
yaml_data = YAML.safe_load(yaml_content)
|
108
|
+
@staging_server = yaml_data['staging_server']
|
109
|
+
logger.info "Artifacts will be staged on '#{@staging_server}'."
|
110
|
+
end
|
111
|
+
|
112
|
+
# A manifest is a staging to-do list. For each '.deb' file create a colon-delimited line
|
113
|
+
# containing:
|
114
|
+
# <.deb filename>:<puppet-version>:<repo-type>:<debian-codename>
|
115
|
+
def generate_manifest
|
116
|
+
manifest_temporary_file = Tempfile.new('apt_stage_artifacts')
|
117
|
+
|
118
|
+
@debian_artifacts.each do |deb_file_path|
|
119
|
+
# Ug. We only know the codename because it happens to be the first element
|
120
|
+
# of the file path.
|
121
|
+
debian_codename = deb_file_path.split('/').first
|
122
|
+
manifest_temporary_file.printf(
|
123
|
+
"%s:%s:%s:%s\n",
|
124
|
+
deb_file_path, @puppet_version, @repo_type, debian_codename
|
125
|
+
)
|
126
|
+
end
|
127
|
+
|
128
|
+
manifest_temporary_file.close
|
129
|
+
manifest_path = File.join(@top_directory, @manifest_file_name)
|
130
|
+
FileUtils.mv(manifest_temporary_file.path, manifest_path)
|
131
|
+
logger.info("Staging manifest written to '#{manifest_path}'")
|
132
|
+
end
|
133
|
+
|
134
|
+
# Create a tarball that contains the staging manifest and the associated deb files.
|
135
|
+
def create_tarball
|
136
|
+
tarball_create_command = %W[
|
137
|
+
tar --create --gzip --file #{@local_tarball_path} --directory=#{@top_directory}
|
138
|
+
].join(' ')
|
139
|
+
%x(#{tarball_create_command} #{@manifest_file_name} #{@debian_artifacts.join(' ')})
|
140
|
+
unless $CHILD_STATUS.success?
|
141
|
+
fatal "#{tarball_create_command} #{@manifest_file_name} #{@debian_artifacts.join(' ')} failed."
|
142
|
+
end
|
143
|
+
|
144
|
+
logger.info("'#{@local_tarball_path}' created.")
|
145
|
+
end
|
146
|
+
|
147
|
+
def cleanup_tarball
|
148
|
+
File.delete @local_tarball_path
|
149
|
+
end
|
150
|
+
|
151
|
+
# The target apt repository is described in the REPO_NAME environment variable.
|
152
|
+
# A better solution is called for, perhaps as part of vanagon config or as a commandline
|
153
|
+
# parameter.
|
154
|
+
def parse_repo_type
|
155
|
+
case ENV['REPO_NAME']
|
156
|
+
when /\A\z/, nil
|
157
|
+
fatal "The environment variable 'REPO_NAME', containing the target apt repo, is unset.\n" \
|
158
|
+
"It should be set to something like 'puppet7' or 'puppet7-nightly'."
|
159
|
+
when /\Apuppet(\d+)\z/
|
160
|
+
@puppet_version = Regexp.last_match(1)
|
161
|
+
@repo_type = 'stable'
|
162
|
+
when /\Apuppet(\d+)-nightly\z/
|
163
|
+
@puppet_version = Regexp.last_match(1)
|
164
|
+
@repo_type = 'nightly'
|
165
|
+
else
|
166
|
+
fatal "The environment variable 'REPO_NAME' is set to '#{ENV['REPO_NAME']}'\n" \
|
167
|
+
"This is not a recognized setting.\n" \
|
168
|
+
"It should be set to something like 'puppet7' or 'puppet7-nightly'."
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Send the tarball over to the staging server for further processing with freight.
|
173
|
+
def ship_tarball_to_staging_server
|
174
|
+
logger.info "Sending '#{@local_tarball_path}' to '#{@staging_server}:#{@remote_tarball_path}'"
|
175
|
+
%x(scp #{@local_tarball_path} #{@staging_server}:#{@remote_tarball_path})
|
176
|
+
return if $CHILD_STATUS.success?
|
177
|
+
|
178
|
+
fatal "'scp #{@local_tarball_path} #{@staging_server}:#{@remote_tarball_path}' failed."
|
179
|
+
end
|
180
|
+
|
181
|
+
# Invoke the remote staging of the sent artifacts
|
182
|
+
def invoke_remote_staging
|
183
|
+
%x(ssh #{@staging_server} #{@remote_staging_command} #{@remote_tarball_path})
|
184
|
+
return if $CHILD_STATUS.success?
|
185
|
+
|
186
|
+
fatal "'ssh #{@staging_server} #{@remote_staging_command} #{@remote_tarball_path}' failed."
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'version'
|
2
|
+
require 'mixins/logging'
|
3
|
+
|
4
|
+
require 'English'
|
5
|
+
require 'mkmf'
|
6
|
+
|
7
|
+
class AptStageFromTarball
|
8
|
+
include Logging
|
9
|
+
|
10
|
+
def initialize(tarball_path = nil)
|
11
|
+
@tarball_path = tarball_path
|
12
|
+
@manifest_file_name = 'apt_stage.manifest'
|
13
|
+
@log_level = Logger::INFO
|
14
|
+
@repo_types_updated = {}
|
15
|
+
|
16
|
+
@script_name = File.basename($PROGRAM_NAME)
|
17
|
+
@version_string = "#{@script_name} version #{AptStageArtifacts::VERSION}"
|
18
|
+
|
19
|
+
# External commands
|
20
|
+
@apt_add_to_freight_library_command = 'apt-add-to-freight-library'
|
21
|
+
@apt_update_freight_cache_command = 'apt-update-freight-cache'
|
22
|
+
end
|
23
|
+
|
24
|
+
def run
|
25
|
+
logger.info @version_string
|
26
|
+
check_for_external_commands
|
27
|
+
extract_tarball
|
28
|
+
add_artifacts_to_freight_library
|
29
|
+
update_freight_cache
|
30
|
+
# cleanup_tarball_directory
|
31
|
+
logger.info 'Freight artifact staging successful.'
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def check_for_external_commands
|
37
|
+
%W[#{@apt_add_to_freight_library_command}
|
38
|
+
#{@apt_update_freight_cache_command}].each do |external_command|
|
39
|
+
fatal "'#{external_command}' is missing or not executable" unless
|
40
|
+
find_executable external_command
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def extract_tarball
|
45
|
+
fatal "'#{@tarball_path}' does not exist." unless File.exist?(@tarball_path)
|
46
|
+
fatal "'#{@tarball_path}' is not a regular file." unless File.file?(@tarball_path)
|
47
|
+
fatal "'#{@tarball_path}' is not readable." unless File.readable?(@tarball_path)
|
48
|
+
|
49
|
+
@tarball_directory = File.dirname(@tarball_path)
|
50
|
+
|
51
|
+
tarball_extract_command = %W[
|
52
|
+
tar --directory #{@tarball_directory} --extract --gzip --file #{@tarball_path}
|
53
|
+
].join(' ')
|
54
|
+
%x(#{tarball_extract_command})
|
55
|
+
|
56
|
+
unless $CHILD_STATUS.success?
|
57
|
+
fatal "#{tarball_extract_command} failed."
|
58
|
+
end
|
59
|
+
|
60
|
+
@manifest_path = File.join(@tarball_directory, @manifest_file_name)
|
61
|
+
|
62
|
+
fatal "Staging manifest file '#{@manifest_path}' is missing or unreadable" unless
|
63
|
+
File.readable?(@manifest_path)
|
64
|
+
|
65
|
+
logger.info("'#{@tarball_path}' extracted.")
|
66
|
+
end
|
67
|
+
|
68
|
+
# Read through the staging manifest, adding each line into the correct apt freight
|
69
|
+
# library.
|
70
|
+
def add_artifacts_to_freight_library
|
71
|
+
Dir.chdir(@tarball_directory) do
|
72
|
+
File.readlines(@manifest_path).each do |line|
|
73
|
+
line.chomp!
|
74
|
+
debian_filename, puppet_version, repo_type, codename = line.split(':')
|
75
|
+
add_to_freight_library_command = %W[
|
76
|
+
#{@apt_add_to_freight_library_command}
|
77
|
+
--verbose
|
78
|
+
--puppet-version=#{puppet_version}
|
79
|
+
--repo-type=#{repo_type}
|
80
|
+
--codename=#{codename}
|
81
|
+
#{File.join(Dir.pwd, debian_filename)}
|
82
|
+
].join(' ')
|
83
|
+
|
84
|
+
%x(#{add_to_freight_library_command})
|
85
|
+
fatal "#{add_to_freight_library_command} failed." unless $CHILD_STATUS.success?
|
86
|
+
|
87
|
+
# Keep a hash, key by puppet_version, of repo_types so that we can
|
88
|
+
# efficiently build out the freight caches later.
|
89
|
+
@repo_types_updated[puppet_version] = [] unless @repo_types_updated.key?(puppet_version)
|
90
|
+
@repo_types_updated[puppet_version] |= [repo_type]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def update_freight_cache
|
96
|
+
@repo_types_updated.each do |puppet_version, repo_types|
|
97
|
+
repo_types.each do |repo_type|
|
98
|
+
update_freight_cache_command = %W[
|
99
|
+
#{@apt_update_freight_cache_command}
|
100
|
+
--verbose
|
101
|
+
--puppet-version=#{puppet_version}
|
102
|
+
--repo-type=#{repo_type}
|
103
|
+
].join(' ')
|
104
|
+
|
105
|
+
%x(#{update_freight_cache_command})
|
106
|
+
fatal "#{update_freight_cache_command} failed." unless $CHILD_STATUS.success?
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'version'
|
2
|
+
require 'mixins/logging'
|
3
|
+
|
4
|
+
require 'English'
|
5
|
+
require 'docopt'
|
6
|
+
require 'open-uri'
|
7
|
+
require 'tempfile'
|
8
|
+
require 'yaml'
|
9
|
+
|
10
|
+
##
|
11
|
+
## This is a wrapper for https://github.com/freight-team/freight, which creates APT repos
|
12
|
+
## from deb files. This triggers the 'freight cache' command which creates a proper
|
13
|
+
## APT repo (freight calls it a 'cache'), including signing, from a tree of debian
|
14
|
+
## files (freight calls it a 'library').
|
15
|
+
##
|
16
|
+
## In our case, we maintain a set of debian repos, based on puppet version and a repo-type
|
17
|
+
## 'nightly', 'archive' and 'stable'.
|
18
|
+
##
|
19
|
+
## freight provides signing services, so this script needs to exist on a machine where GPG
|
20
|
+
## signing has been set up.
|
21
|
+
##
|
22
|
+
## Example usages:
|
23
|
+
## apt-update-freight-cache --puppet-version=7 --repo-type=stable
|
24
|
+
## apt-update-freight-cache --puppet-version=7 --repo-type=nightly
|
25
|
+
|
26
|
+
class AptUpdateFreightCache
|
27
|
+
include Logging
|
28
|
+
|
29
|
+
FREIGHT_COMMAND = '/usr/bin/freight'
|
30
|
+
VALID_PUPPET_VERSIONS = %w[6 7 8]
|
31
|
+
VALID_REPO_TYPES = %w[archive nightly stable]
|
32
|
+
|
33
|
+
DOCUMENTATION = <<~DOCOPT
|
34
|
+
Generates a freight cache from a freight library.
|
35
|
+
|
36
|
+
Usage:
|
37
|
+
apt-update-freight-cache [--verbose] --puppet-version=VERSION --repo-type=REPO_TYPE
|
38
|
+
apt-update-freight-cache --help
|
39
|
+
apt-update-freight-cache --version
|
40
|
+
|
41
|
+
Options:
|
42
|
+
-p --puppet-version=VERSION Puppet version (Valid: #{VALID_PUPPET_VERSIONS.join(', ')})
|
43
|
+
-r --repo-type=REPO_TYPE Puppet debian repo type (Valid: #{VALID_REPO_TYPES.join(', ')})
|
44
|
+
|
45
|
+
-v --verbose Be verbose
|
46
|
+
-h --help Show this help
|
47
|
+
--version Show version
|
48
|
+
DOCOPT
|
49
|
+
|
50
|
+
def initialize(argv)
|
51
|
+
@log_level = Logger::INFO
|
52
|
+
@user_options = parse_options(argv)
|
53
|
+
@verbose = ''
|
54
|
+
@verbose = '--verbose' if @user_options['--verbose']
|
55
|
+
@builder_data_yaml = 'https://raw.githubusercontent.com/puppetlabs/build-data/release/builder_data.yaml'
|
56
|
+
@script_name = File.basename($PROGRAM_NAME)
|
57
|
+
@version_string = "#{@script_name} version #{AptStageArtifacts::VERSION}"
|
58
|
+
if @user_options['--version'] # rubocop:disable Style/GuardClause
|
59
|
+
puts @version_string
|
60
|
+
exit 0
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def parse_options(argv = nil)
|
65
|
+
Docopt.docopt(DOCUMENTATION, { argv: argv })
|
66
|
+
rescue Docopt::Exit => e
|
67
|
+
puts e.message
|
68
|
+
exit 1
|
69
|
+
end
|
70
|
+
|
71
|
+
def run
|
72
|
+
logger.info @version_string
|
73
|
+
load_builder_data_yaml
|
74
|
+
@puppet_version = @user_options['--puppet-version']
|
75
|
+
fatal "Invalid Puppet version '#{@puppet_version}'" unless
|
76
|
+
VALID_PUPPET_VERSIONS.include? @puppet_version
|
77
|
+
|
78
|
+
@repo_type = @user_options['--repo-type']
|
79
|
+
fatal "Invalid repo type '#{@repo_type}'" unless VALID_REPO_TYPES.include? @repo_type
|
80
|
+
|
81
|
+
freight_config_file = "/etc/freight.conf.d/puppet_#{@puppet_version}_#{@repo_type}.conf"
|
82
|
+
fatal "Cannot read '#{freight_config_file} on #{`hostname`.chomp}." unless
|
83
|
+
File.readable?(freight_config_file)
|
84
|
+
|
85
|
+
logger.info "Using '#{freight_config_file}'"
|
86
|
+
freight_cache_command = %W[
|
87
|
+
sudo --user=jenkins --set-home
|
88
|
+
/usr/local/bin/freight-cache-wrapper #{@verbose}
|
89
|
+
--conf=#{freight_config_file} --gpg-key=#{@gpg_key}
|
90
|
+
].join(' ')
|
91
|
+
%x(#{freight_cache_command})
|
92
|
+
fatal "#{tarball_extract_command} failed." unless $CHILD_STATUS.success?
|
93
|
+
end
|
94
|
+
|
95
|
+
# Load details from the builder_data.yaml on github
|
96
|
+
# Keep only the bare necessities. Right now, that's just the GPG key
|
97
|
+
def load_builder_data_yaml
|
98
|
+
yaml_content = URI.parse(@builder_data_yaml).open(&:read)
|
99
|
+
yaml_data = YAML.safe_load(yaml_content)
|
100
|
+
@gpg_key = yaml_data['gpg_key']
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Handles all logging output for Tefoji
|
2
|
+
|
3
|
+
module Logging
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
# A cheap hack that will instantiate a logger if necessary before sending a log
|
7
|
+
# message. This is the normal interface to logging from outside.
|
8
|
+
def logger
|
9
|
+
Logging.logger(@log_level)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Another cheap hack to wrap 'logger' above. Called as 'fatal' rather than 'logger.fatal'
|
13
|
+
# directly, does the exit for us so we can be lazy.
|
14
|
+
def fatal(message)
|
15
|
+
logger.fatal(message)
|
16
|
+
exit 1
|
17
|
+
end
|
18
|
+
|
19
|
+
# Do the actual logging by wrapping Logger gem.
|
20
|
+
def self.logger(log_level)
|
21
|
+
return @logger unless @logger.nil?
|
22
|
+
|
23
|
+
@logger = Logger.new($stderr, progname: File.basename($PROGRAM_NAME), level: log_level)
|
24
|
+
@logger.formatter = proc do |severity, _, script_name, message|
|
25
|
+
"#{script_name}: #{severity} #{message}\n"
|
26
|
+
end
|
27
|
+
return @logger
|
28
|
+
end
|
29
|
+
end
|
data/lib/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: apt_stage_artifacts
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Puppet Release Engineering
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-04-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: pry
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.14'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.14'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry-byebug
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '13.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '13.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop-rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop-rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: yard
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.9'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.9'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: docopt
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description:
|
126
|
+
email:
|
127
|
+
- release@puppet.com
|
128
|
+
executables:
|
129
|
+
- apt-add-to-freight-library
|
130
|
+
- apt-stage-artifacts
|
131
|
+
- apt-stage-from-tarball
|
132
|
+
- apt-update-freight-cache
|
133
|
+
extensions: []
|
134
|
+
extra_rdoc_files: []
|
135
|
+
files:
|
136
|
+
- ".gitignore"
|
137
|
+
- ".rspec"
|
138
|
+
- ".rubocop.yml"
|
139
|
+
- CHANGELOG.md
|
140
|
+
- CODEOWNERS
|
141
|
+
- DEVELOPMENT.md
|
142
|
+
- Gemfile
|
143
|
+
- LICENSE.txt
|
144
|
+
- README.md
|
145
|
+
- Rakefile
|
146
|
+
- apt_stage_artifacts.gemspec
|
147
|
+
- bin/console
|
148
|
+
- bin/setup
|
149
|
+
- exe/apt-add-to-freight-library
|
150
|
+
- exe/apt-stage-artifacts
|
151
|
+
- exe/apt-stage-from-tarball
|
152
|
+
- exe/apt-update-freight-cache
|
153
|
+
- lib/apt_add_to_freight_library.rb
|
154
|
+
- lib/apt_stage_artifacts.rb
|
155
|
+
- lib/apt_stage_from_tarball.rb
|
156
|
+
- lib/apt_update_freight_cache.rb
|
157
|
+
- lib/mixins/logging.rb
|
158
|
+
- lib/version.rb
|
159
|
+
homepage: https://github.com/puppetlabs/apt_stage_artifacts
|
160
|
+
licenses: []
|
161
|
+
metadata:
|
162
|
+
allowed_push_host: https://rubygems.org
|
163
|
+
homepage_uri: https://github.com/puppetlabs/apt_stage_artifacts
|
164
|
+
source_code_uri: https://github.com/puppetlabs/apt_stage_artifacts
|
165
|
+
changelog_uri: https://github.com/puppetlabs/apt_stage_artifacts/CHANGELOG.md
|
166
|
+
post_install_message:
|
167
|
+
rdoc_options: []
|
168
|
+
require_paths:
|
169
|
+
- lib
|
170
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
171
|
+
requirements:
|
172
|
+
- - ">="
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: 2.5.0
|
175
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
176
|
+
requirements:
|
177
|
+
- - ">="
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: '0'
|
180
|
+
requirements: []
|
181
|
+
rubygems_version: 3.1.4
|
182
|
+
signing_key:
|
183
|
+
specification_version: 4
|
184
|
+
summary: Stages .deb artifacts to a remote freight repository
|
185
|
+
test_files: []
|