repo-mgr 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: be8fb6163c79ae7f9956b0237f390c4d7764c23ef6f4ffa24c1531a3726187e0
4
- data.tar.gz: 60346b9d260718f3a03745b6c90b1fdb80c34ac62458cd999d67a2cadc7b840d
3
+ metadata.gz: 134dd25e2f420da28416738476d2461cfc4e41e358b9eeefd95740b12fb32b29
4
+ data.tar.gz: 583f3afd307e6b101df5fb316619c8636882388d93937fe8cd66200d302c03e7
5
5
  SHA512:
6
- metadata.gz: 8af9d6f12205d03e88d28ed848331708a9c6313ea377fd9c9144a2a2f88070de904784cc63659a42b9f3d110775caeeea636d90953927ed645039f135873eaf9
7
- data.tar.gz: 4688c21a24223d81a0b7fb1c9694a59e26cc7b125c4466aecf9a3bbc470c74619d6a2aa61f7469c9acc993c9f48ac4267fece461bc9738018bea819f5019214a
6
+ metadata.gz: 88e36dd2757d71c32276fa7a7c02c218a0f3dcc2c497b87264388e0ef9a9cd65308b35588ae3b967073ddb823c6bdb3310be6eb47b87f18a63de75526d6b039e
7
+ data.tar.gz: 0bf223130b5aee561025db95edf42322e09071767c43d2ceddaeee77317a1a808fde24f994cf9995c1e4299424e26ecda35aa0222a047bf6ef6b7ecc0d6d883d
data/README.md CHANGED
@@ -9,8 +9,12 @@ Features:
9
9
  * Create/update deb/rpm repositories.
10
10
  * Add/remove packages to these repositories and automatically sign packages using GPG.
11
11
  * Repository metadata/manifest signing using GPG.
12
+ * Publish to remote via git.
12
13
 
13
- To simplify things, aptly (which, kind of obviously, manages deb repositories) uses "stable" as distribution and "main" as component.
14
+ To simplify things:
15
+
16
+ * aptly (which, kind of obviously, manages deb repositories) uses "stable" as distribution and "main" as component.
17
+ * The git publisher uses the `main` branch for `sync` only.
14
18
 
15
19
  ## Install
16
20
 
@@ -35,6 +39,7 @@ repo-mgr check-depends
35
39
  | dpkg-sig | ✔ |
36
40
  | createrepo | ✔ |
37
41
  | rpm | ✔ |
42
+ | git | ✔ |
38
43
  +------------+--------+
39
44
  ```
40
45
 
@@ -48,6 +53,12 @@ For managing rpm repositories:
48
53
 
49
54
  ```bash
50
55
  sudo apt install createrepo rpm
56
+ ```
57
+
58
+ For using the git publisher:
59
+
60
+ ```bash
61
+ sudo apt install git
51
62
  ```
52
63
 
53
64
  n.b `createrepo` is not normally available for Debian and derrivates (including Ubuntu). This tool
@@ -65,11 +76,27 @@ repo-mgr help
65
76
  # create repo
66
77
  ## --path => a local directory where the repository is published - no remote support at the moment
67
78
  ## GPGKEYID is expected as log keyid i.e 16 hex chars
68
- repo-mgr upsert-repo --name foo --type deb --path path/to/foo --keyid GPGKEYID
79
+ ## --publisher - is optional i.e you can still manually publish a local repository
80
+ repo-mgr upsert-repo --name foo --type deb --path path/to/foo --keyid GPGKEYID --publisher git
69
81
 
70
82
  # sign package, add to repository, and update local repo (includes sign repo release manifest)
71
83
  # the local repo is exported to the path indicated in upsert-repo
84
+ # the git publisher also commits the changes as the path for upsert-repo is expected to be
85
+ # a git repository
72
86
  repo-mgr add-pkg --repo foo --path path/to/bar_0.0.1_amd64.deb
87
+
88
+ # publish the repository to a remote - for git publisher this means doing git push
89
+ repo-mgr sync --repo foo
90
+ ```
91
+
92
+ ## Migrating from v0.1
93
+
94
+ The package list is stored into a structure that's prone to lose the list upon re-running `upsert-repo` for `v0.1.x` of this gem. For this reason, the package list data structure has been redesigned within repo-mgr's config file.
95
+
96
+ So, to migrate from this earlier version, you must run, for every repo:
97
+
98
+ ```bash
99
+ repo-mgr rebuild-pkg-list --repo foo
73
100
  ```
74
101
 
75
- You then need to sync the repo to whatever desired target. For the time being, this isn't implemented as the main use case for this tool is publishing into a git repository which is served as GitHub page.
102
+ This rebuilds the data structure in the new config location.
@@ -45,7 +45,7 @@ module RepoMgr
45
45
  repo_publish repo
46
46
  end
47
47
 
48
- def check_sig(pkg, allow_fail = false)
48
+ def check_sig(pkg, allow_fail: false)
49
49
  out, status = Open3.capture2e "dpkg-sig --verify #{pkg}"
50
50
 
51
51
  return out if status.exitstatus.zero? || allow_fail
@@ -55,7 +55,7 @@ module RepoMgr
55
55
  end
56
56
 
57
57
  def sign_pkg(repo, pkg)
58
- signature = check_sig pkg, true
58
+ signature = check_sig pkg, allow_fail: true
59
59
 
60
60
  unless signature[-6, 5] == 'NOSIG'
61
61
  return puts "-- dpkg-sig returned:\n#{signature.first}"
@@ -73,6 +73,21 @@ module RepoMgr
73
73
  Tools.error "unable to sign #{pkg} - dpkg-sig returned:\n#{out}"
74
74
  end
75
75
 
76
+ def rebuild_pkg_list(repo)
77
+ out, status = Open3.capture2e "aptly -config=#{@aptly_config_file} "\
78
+ "-with-packages repo show #{repo}"
79
+
80
+ unless status.exitstatus.zero?
81
+ Tools.error "aptly repo show failed with with:\n#{out}"
82
+ end
83
+
84
+ pkgs = out.split
85
+ mark = pkgs.find_index 'Packages:'
86
+ pkgs = pkgs.drop(mark + 1)
87
+
88
+ pkgs.map { |e| "#{e}.deb" }
89
+ end
90
+
76
91
  private
77
92
 
78
93
  def init_aptly_config
@@ -69,6 +69,12 @@ module RepoMgr
69
69
  Tools.error "unable to sign #{pkg} - rpm --addsign returned:\n#{out}"
70
70
  end
71
71
 
72
+ def rebuild_pkg_list(repo)
73
+ Dir["#{@config.cfg_dir}/rpms/#{repo}/**/*.rpm"].map do |e|
74
+ File.basename e
75
+ end
76
+ end
77
+
72
78
  private
73
79
 
74
80
  def extract_arch(pkg)
data/lib/repo_mgr/cli.rb CHANGED
@@ -8,6 +8,7 @@ require 'terminal-table'
8
8
  require_relative 'tools'
9
9
  require_relative 'config'
10
10
  require_relative 'backends'
11
+ require_relative 'publishers'
11
12
 
12
13
  module RepoMgr
13
14
  # implements CLI interface
@@ -20,12 +21,16 @@ module RepoMgr
20
21
  %w[deb rpm]
21
22
  end
22
23
 
24
+ def self.publishers
25
+ %w[git]
26
+ end
27
+
23
28
  desc 'check-depends', 'Check dependencies'
24
29
 
25
30
  def check_depends
26
31
  rows = []
27
32
 
28
- %w[aptly dpkg-sig createrepo rpm].each do |bin_dep|
33
+ %w[aptly dpkg-sig createrepo rpm git].each do |bin_dep|
29
34
  rows << if Tools.which bin_dep
30
35
  [bin_dep, '✔'.green]
31
36
  else
@@ -45,13 +50,14 @@ module RepoMgr
45
50
  desc: 'Directory path where to build the repository'
46
51
  option :keyid, type: :string, required: true, aliases: %w[-k],
47
52
  desc: 'GPG key id used to sign the repository metadata'
53
+ option :publisher, type: :string, aliases: %w[-r], enum: publishers,
54
+ desc: 'Publisher used to sync repo data to remote target'
48
55
 
49
56
  def upsert_repo
50
57
  FileUtils.mkdir_p options[:path]
51
58
 
52
59
  config = Config.new
53
- config.upsert_repo options[:name], options[:type], options[:path],
54
- options[:keyid]
60
+ config.upsert_repo options
55
61
 
56
62
  backend = Backends.load options[:type], config
57
63
  backend.add_repo options[:name]
@@ -66,12 +72,14 @@ module RepoMgr
66
72
  config = Config.new
67
73
 
68
74
  config.cfg[:repos].each do |name, repo|
69
- rows << [name, repo[:type], repo[:path], repo[:keyid]]
75
+ rows << [name, repo[:type], repo[:path], repo[:keyid], repo[:publisher]]
70
76
  end
71
77
 
72
78
  return puts '-- No repos have been created' if rows.count.zero?
73
79
 
74
- puts Terminal::Table.new headings: %w[Name Type Path KeyID], rows: rows
80
+ puts Terminal::Table.new(
81
+ headings: %w[Name Type Path KeyID Publisher], rows: rows
82
+ )
75
83
  end
76
84
 
77
85
  desc 'add-pkg', 'Add package to repository'
@@ -85,6 +93,12 @@ module RepoMgr
85
93
  backend.add_pkg options[:repo], options[:path]
86
94
  config.add_pkg options[:repo], options[:path]
87
95
 
96
+ pub_type = config.cfg[:repos][options[:repo]][:publisher]
97
+ if pub_type
98
+ publisher = Publishers.load pub_type, config
99
+ publisher.save options[:repo], options[:path]
100
+ end
101
+
88
102
  puts "-- Added #{File.basename(options[:path])} to "\
89
103
  "#{options[:repo]} repository"
90
104
  end
@@ -94,7 +108,7 @@ module RepoMgr
94
108
  desc: 'The repository to list the packages from'
95
109
 
96
110
  def list_pkgs
97
- packages = Config.new.cfg[:repos][options[:repo]][:packages]
111
+ packages = Config.new.cfg[:packages][options[:repo]]
98
112
 
99
113
  if packages.nil?
100
114
  Tools.error "#{options[:repo]} repo does not have any packages"
@@ -130,6 +144,38 @@ module RepoMgr
130
144
  puts backend.check_sig options[:path]
131
145
  end
132
146
 
147
+ desc 'rebuild-pkg-list', 'Rebuild package list from local pkg cache'
148
+ option :repo, type: :string, required: true, aliases: %w[-r],
149
+ desc: 'The repository to rebuild pkg list for'
150
+ def rebuild_pkg_list
151
+ config = Config.new
152
+ backend = Backends.load config.cfg[:repos][options[:repo]][:type], config
153
+ pkgs = backend.rebuild_pkg_list options[:repo]
154
+
155
+ pkgs.each do |pkg|
156
+ config.add_pkg options[:repo], pkg
157
+ end
158
+
159
+ puts "-- Rebuilt #{options[:repo]} repo pkg list"
160
+ end
161
+
162
+ desc 'sync', 'Sync local repo to remote target using repo publisher'
163
+ option :repo, type: :string, required: true, aliases: %w[-r],
164
+ desc: 'The repository to sync to remote target via publisher'
165
+ def sync
166
+ config = Config.new
167
+ pub_type = config.cfg[:repos][options[:repo]][:publisher]
168
+
169
+ unless pub_type
170
+ Tools.error "#{options[:repo]} repo does not have a publisher"
171
+ end
172
+
173
+ publisher = Publishers.load pub_type, config
174
+ publisher.sync options[:repo]
175
+
176
+ puts "-- Synchronised #{options[:repo]} using #{pub_type} publisher"
177
+ end
178
+
133
179
  private
134
180
 
135
181
  def load_backend(path)
@@ -15,7 +15,9 @@ module RepoMgr
15
15
  FileUtils.mkdir_p @cfg_dir
16
16
 
17
17
  @cfg_file = "#{@cfg_dir}/repo-mgr.yml"
18
- File.write @cfg_file, { repos: {} }.to_yaml unless File.exist? @cfg_file
18
+ unless File.exist? @cfg_file
19
+ File.write @cfg_file, { repos: {}, packages: {} }.to_yaml
20
+ end
19
21
 
20
22
  @cfg = YAML.load_file @cfg_file
21
23
  end
@@ -24,17 +26,24 @@ module RepoMgr
24
26
  File.write @cfg_file, @cfg.to_yaml
25
27
  end
26
28
 
27
- def upsert_repo(name, type, path, keyid)
29
+ def upsert_repo(options)
30
+ name = options[:name]
31
+ type = options[:type]
32
+
28
33
  if @cfg[:repos][name] && @cfg[:repos][name][:type] != type
29
34
  Tools.error "unable to change type for #{name} repository"
30
35
  end
31
36
 
32
37
  @cfg[:repos][name] = {
33
38
  type: type,
34
- path: path,
35
- keyid: keyid
39
+ path: options[:path],
40
+ keyid: options[:keyid]
36
41
  }
37
42
 
43
+ if options[:publisher]
44
+ @cfg[:repos][name][:publisher] = options[:publisher]
45
+ end
46
+
38
47
  save
39
48
  end
40
49
 
@@ -43,14 +52,15 @@ module RepoMgr
43
52
  Tools.error "unable to add packages to #{repo} - repo does not exist"
44
53
  end
45
54
 
46
- @cfg[:repos][repo][:packages] ||= []
55
+ @cfg[:packages] ||= {}
56
+ @cfg[:packages][repo] ||= []
47
57
  pkg = File.basename path
48
58
 
49
- if @cfg[:repos][repo][:packages].include?(pkg)
59
+ if @cfg[:packages][repo].include?(pkg)
50
60
  Tools.error "you already have #{pkg} in your #{repo} repo"
51
61
  end
52
62
 
53
- @cfg[:repos][repo][:packages] << pkg
63
+ @cfg[:packages][repo] << pkg
54
64
 
55
65
  save
56
66
  end
@@ -61,9 +71,10 @@ module RepoMgr
61
71
  '- repo does not exist'
62
72
  end
63
73
 
64
- @cfg[:repos][repo][:packages] ||= []
74
+ @cfg[:packages] ||= {}
75
+ @cfg[:packages][repo] ||= []
65
76
  pkg = File.basename path
66
- @cfg[:repos][repo][:packages].delete pkg
77
+ @cfg[:packages][repo].delete pkg
67
78
 
68
79
  save
69
80
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: false
2
+
3
+ require_relative 'publishers/git'
4
+
5
+ module RepoMgr
6
+ # factory loader for RepoMgr::Publisher::Foo objects
7
+ class Publishers
8
+ def self.load(publisher, config)
9
+ @obj ||= {}
10
+
11
+ @obj[publisher] ||= Object.const_get(
12
+ "RepoMgr::Publisher::#{publisher.capitalize}"
13
+ ).new(config)
14
+
15
+ @obj[publisher]
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: false
2
+
3
+ require 'git'
4
+
5
+ module RepoMgr
6
+ module Publisher
7
+ # git publisher
8
+ class Git
9
+ def initialize(config)
10
+ @config = config
11
+ end
12
+
13
+ # method invoked when the local deb/rpm repository is built
14
+ # for git, this requires a commit into the target git repository
15
+ # which is the target for deb/rpm repository export
16
+ def save(repo, pkg)
17
+ git = ::Git.open @config.cfg[:repos][repo][:path]
18
+ git.add(all: true)
19
+ git.commit "Add #{File.basename(pkg)}."
20
+ end
21
+
22
+ # method invoked when the local deb/rpm repository is published
23
+ # for git, this is pushing to a remote
24
+ def sync(repo)
25
+ git = ::Git.open @config.cfg[:repos][repo][:path]
26
+ git.push(git.remote('origin'), 'main')
27
+ end
28
+ end
29
+ end
30
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: repo-mgr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ștefan Rusu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-17 00:00:00.000000000 Z
11
+ date: 2021-04-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colored
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: git
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.8.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.8.1
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: gpgme
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -140,6 +154,8 @@ files:
140
154
  - lib/repo_mgr/backends/rpm.rb
141
155
  - lib/repo_mgr/cli.rb
142
156
  - lib/repo_mgr/config.rb
157
+ - lib/repo_mgr/publishers.rb
158
+ - lib/repo_mgr/publishers/git.rb
143
159
  - lib/repo_mgr/tools.rb
144
160
  homepage: https://github.com/mr-staker/repo-mgr
145
161
  licenses: