apt_stage_artifacts 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|