puppet-forge-server 1.8.0 → 1.9.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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -0
  3. data/.travis.yml +3 -0
  4. data/lib/puppet_forge_server.rb +4 -0
  5. data/lib/puppet_forge_server/api/v1/modules.rb +7 -3
  6. data/lib/puppet_forge_server/api/v3/modules.rb +7 -2
  7. data/lib/puppet_forge_server/api/v3/releases.rb +9 -4
  8. data/lib/puppet_forge_server/app/frontend.rb +19 -0
  9. data/lib/puppet_forge_server/app/public/css/puppetlabs.css +236 -0
  10. data/lib/puppet_forge_server/app/views/layout.haml +1 -1
  11. data/lib/puppet_forge_server/app/views/module.haml +71 -0
  12. data/lib/puppet_forge_server/app/views/modules.haml +1 -1
  13. data/lib/puppet_forge_server/backends/directory.rb +12 -5
  14. data/lib/puppet_forge_server/backends/proxy.rb +29 -4
  15. data/lib/puppet_forge_server/backends/proxy_v3.rb +20 -6
  16. data/lib/puppet_forge_server/http/http_client.rb +29 -2
  17. data/lib/puppet_forge_server/logger.rb +9 -2
  18. data/lib/puppet_forge_server/models/builder.rb +6 -1
  19. data/lib/puppet_forge_server/models/metadata.rb +1 -1
  20. data/lib/puppet_forge_server/models/module.rb +2 -2
  21. data/lib/puppet_forge_server/server.rb +2 -0
  22. data/lib/puppet_forge_server/utils/archiver.rb +3 -1
  23. data/lib/puppet_forge_server/utils/cache_provider.rb +42 -0
  24. data/lib/puppet_forge_server/utils/encoding.rb +46 -0
  25. data/lib/puppet_forge_server/utils/filtering_inspecter.rb +30 -0
  26. data/lib/puppet_forge_server/utils/md_renderer.rb +54 -0
  27. data/lib/puppet_forge_server/utils/option_parser.rb +23 -1
  28. data/lib/puppet_forge_server/version.rb +1 -1
  29. data/puppet-forge-server.gemspec +8 -0
  30. data/spec/spec_helper.rb +41 -1
  31. data/spec/unit/http/http_client_spec.rb +93 -0
  32. data/spec/unit/utils/encoding_spec.rb +35 -0
  33. metadata +110 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 520c95153ba62be7304bec30c3d12e4f560c84ba
4
- data.tar.gz: 001d53cfa31b811b843b88c0f80174500822f383
3
+ metadata.gz: 08f079588ee75d93139153846fb0021ffd6e856a
4
+ data.tar.gz: 985dd8259b92e2a616e2ea00dcb4ac906572fb69
5
5
  SHA512:
6
- metadata.gz: 6c56267829a2b368b604178d383c78ea8860cc008e7182732db8e87b64fbbc3cc72259f07c8cc7becc69315bddf2ffb9b450456d9fec40ace00bd3a7a6d49b71
7
- data.tar.gz: 9538e370e0c68fbb1f9179ee3781059a618f3e38f85e2d124bad82749b9ae6bbfa04d058cebe923589c06ffcd9adf5536359dcad5d73a19e613e61d0f060e6d9
6
+ metadata.gz: 3bb6e219dd02e6484fab928c5c5047bf51329facd1fc1d2acd4613c79f4e22bc1fce66f4709302c0b57d24137417b23a8cd1b37c64b149e7f6e48cbc5186a438
7
+ data.tar.gz: 4abba59d6b0cc3c16a65534940a37187286207ba273936dcf0c0b6d859c7a851cb055a549aecdaaf551797817cd08f3ab711341cc67223aac54fa175543bb8d6
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -19,5 +19,8 @@ rvm:
19
19
  - 1.9.3
20
20
  - 2.0.0
21
21
 
22
+ before_install:
23
+ - gem update bundler
24
+
22
25
  script:
23
26
  - bundle exec rake test:all
@@ -56,10 +56,14 @@ module PuppetForgeServer
56
56
  end
57
57
 
58
58
  module Utils
59
+ autoload :CacheProvider, 'puppet_forge_server/utils/cache_provider'
60
+ autoload :FilteringInspecter, 'puppet_forge_server/utils/filtering_inspecter'
59
61
  autoload :Archiver, 'puppet_forge_server/utils/archiver'
60
62
  autoload :OptionParser, 'puppet_forge_server/utils/option_parser'
61
63
  autoload :Buffer, 'puppet_forge_server/utils/buffer'
62
64
  autoload :Http, 'puppet_forge_server/utils/http'
65
+ autoload :MarkdownRenderer, 'puppet_forge_server/utils/md_renderer'
66
+ autoload :Encoding, 'puppet_forge_server/utils/encoding'
63
67
  end
64
68
 
65
69
  module Http
@@ -29,16 +29,20 @@ module PuppetForgeServer::Api::V1
29
29
  modules[element.metadata.name][:releases] = (modules[element.metadata.name][:releases] + releases_version(element.metadata)).uniq.sort_by { |r| Gem::Version.new(r[:version]) }.reverse
30
30
  modules[element.metadata.name][:tag_list] = (modules[element.metadata.name][:tag_list] + element.tags).uniq.compact
31
31
  else
32
- name = element.metadata.name.sub(/^[^-]+-/, '')
32
+ author, name = element.metadata.name.split('-')
33
+ unless name
34
+ name = author
35
+ author = element.metadata.author
36
+ end
33
37
  modules[element.metadata.name] = {
34
- :author => element.metadata.author,
38
+ :author => author,
35
39
  :full_name => element.metadata.name.sub('-', '/'),
36
40
  :name => name,
37
41
  :desc => element.metadata.description,
38
42
  :version => element.metadata.version,
39
43
  :project_url => element.metadata.project_page,
40
44
  :releases => releases_version(element.metadata),
41
- :tag_list => element.tags ? element.tags : [element.metadata.author, name],
45
+ :tag_list => element.tags ? element.tags : [author, name],
42
46
  :private => element.private
43
47
  }
44
48
  end
@@ -30,14 +30,19 @@ module PuppetForgeServer::Api::V3
30
30
  end
31
31
  modules[element.metadata.name][:releases] = (modules[element.metadata.name][:releases] + releases_version(element.metadata)).uniq.sort_by { |r| Gem::Version.new(r[:version]) }.reverse
32
32
  else
33
+ author, name = element.metadata.name.split('-')
34
+ unless name
35
+ name = author
36
+ author = element.metadata.author
37
+ end
33
38
  modules[element.metadata.name] = {
34
39
  :uri => "/v3/modules/#{element.metadata.name}",
35
- :name => element.metadata.name.sub(/^[^-]+-/, ''),
40
+ :name => name,
36
41
  :homepage_url => element.metadata.project_page,
37
42
  :issues_url => element.metadata.issues_url,
38
43
  :releases => releases_version(element.metadata),
39
44
  :current_release => get_releases([element]).first,
40
- :owner => {:username => element.metadata.author, :uri => "/v3/users/#{element.metadata.author}"},
45
+ :owner => {:username => author, :uri => "/v3/users/#{author}"},
41
46
  :private => element.private
42
47
  }
43
48
  end
@@ -16,10 +16,14 @@
16
16
 
17
17
  module PuppetForgeServer::Api::V3
18
18
  module Releases
19
+ include PuppetForgeServer::Utils::Encoding
19
20
  def get_releases(metadata)
20
21
  metadata.map do |element|
21
- name = element.metadata.name.sub(/^[^-]+-/, '')
22
- author = element.metadata.name.split('-')[0]
22
+ author, name = element.metadata.name.split('-')
23
+ unless name
24
+ name = author
25
+ author = element.metadata.author
26
+ end
23
27
  {
24
28
  :uri => "/v3/releases/#{element.metadata.name}-#{element.metadata.version}",
25
29
  :module => {
@@ -29,10 +33,11 @@ module PuppetForgeServer::Api::V3
29
33
  },
30
34
  :metadata => element.metadata.to_hash,
31
35
  :version => element.metadata.version,
32
- :tags => element.tags ? element.tags : [element.metadata.author, name],
36
+ :tags => element.tags ? element.tags : [author, name],
33
37
  :file_uri => "/v3/files#{element.path}",
34
38
  :file_md5 => element.checksum,
35
- :deleted_at => element.deleted_at
39
+ :deleted_at => element.deleted_at,
40
+ :readme => to_utf8(element.readme)
36
41
  }
37
42
  end.uniq{|r| r[:version]}.sort_by { |r| Gem::Version.new(r[:version]) }
38
43
  end
@@ -17,9 +17,11 @@
17
17
  require 'sinatra/base'
18
18
  require 'haml'
19
19
  require 'json'
20
+ require 'tilt/haml'
20
21
 
21
22
  module PuppetForgeServer::App
22
23
  class Frontend < Sinatra::Base
24
+ include PuppetForgeServer::Utils::MarkdownRenderer
23
25
 
24
26
  configure do
25
27
  set :haml, :format => :html5
@@ -47,6 +49,23 @@ module PuppetForgeServer::App
47
49
  haml :modules, :locals => {:query => query, :modules => modules}
48
50
  end
49
51
 
52
+ get '/module' do
53
+ module_v3_name = params[:name].gsub(/\//, '-')
54
+ releases = get("#{request.base_url}/v3/modules/#{module_v3_name}")['releases']
55
+ if params.has_key? 'version'
56
+ module_uri = releases.find {|r| r['version'] == params['version']}['uri']
57
+ module_metadata = get("#{request.base_url}#{module_uri}")
58
+ else
59
+ module_metadata = get("#{request.base_url}#{releases[0]['uri']}")
60
+ end
61
+ begin
62
+ readme_markdown = markdown(module_metadata['readme'])
63
+ rescue
64
+ readme_markdown = ''
65
+ end
66
+ haml :module, :locals => { :module_metadata => module_metadata, :base_url => request.base_url, :readme_markdown => readme_markdown, :releases => releases }
67
+ end
68
+
50
69
  get '/upload' do
51
70
  haml :upload, :locals => {:upload_status => ''}
52
71
  end
@@ -16,6 +16,7 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
+ @import url(https://fonts.googleapis.com/css?family=PT+Sans&subset=latin,latin-ext);
19
20
  body {
20
21
  background: #fff;
21
22
  color: #5d5e59;
@@ -215,6 +216,214 @@ h3.search-results-title {
215
216
  margin: 0;
216
217
  border-bottom: solid 1px #cccccc;
217
218
  }
219
+ .module-header {
220
+ position: relative;
221
+ float: left;
222
+ width: 90%;
223
+ min-height: 77px;
224
+ padding: 1em;
225
+ background-color: #f4f4f4;
226
+ }
227
+ .module-header.supported {
228
+ background-image: url("/assets/41dfc34/images/supported-tag-upper-right.png");
229
+ background-repeat: no-repeat;
230
+ background-position: top right;
231
+ }
232
+ .module-header.approved {
233
+ background-image: url("/assets/41dfc34/images/approved-tag-upper-right.png");
234
+ background-repeat: no-repeat;
235
+ background-position: top right;
236
+ }
237
+ .module-header .author,
238
+ .module-header .tag-section {
239
+ padding-top: 0.25em;
240
+ }
241
+ .module-header .popular {
242
+ display: inline;
243
+ margin-left: 0;
244
+ }
245
+ .module-header .tags {
246
+ display: inline;
247
+ margin-left: 0;
248
+ }
249
+ .module-header .endorsement-trigger {
250
+ position: absolute;
251
+ top: 0;
252
+ right: 0;
253
+ width: 77px;
254
+ height: 77px;
255
+ }
256
+ .module-header .details {
257
+ font-size: 0.95em;
258
+ }
259
+ .module-header .details table {
260
+ width: 100%;
261
+ position: relative;
262
+ }
263
+ .module-header .details .gravatar {
264
+ float: left;
265
+ width: 77px;
266
+ }
267
+ .module-header .details .gravatar .avatar {
268
+ margin: 0;
269
+ padding: 0;
270
+ }
271
+ .module-header .details .module-info-basic {
272
+ margin-left: 93px;
273
+ /* width of gravatar (77) + 1em (16) */
274
+ }
275
+ .module-header .details .module-info-basic .module-info-header {
276
+ margin: 0;
277
+ padding-right: 45px;
278
+ }
279
+ .module-header .details .module-info-basic .module-info-header a:hover {
280
+ text-decoration: underline;
281
+ }
282
+ .module-header .details .module-info-basic .module-info-header h2 {
283
+ display: inline-block;
284
+ margin: 0 10px 0 0;
285
+ line-height: 1.1rem;
286
+ }
287
+ @media (max-width: 1150px) {
288
+ .module-header .details .module-info-basic .module-info-header h2 .namespace {
289
+ display: none;
290
+ }
291
+ }
292
+ .module-header .details .module-info-basic .module-info-header .module-info-author {
293
+ display: inline-block;
294
+ margin-right: 15px;
295
+ font-size: 12px;
296
+ white-space: nowrap;
297
+ }
298
+ .module-header .details .module-info-basic .module-info-header .module-links {
299
+ display: inline-block;
300
+ font-size: 12px;
301
+ }
302
+ .module-header .details .module-info-basic .module-info-header .module-links li {
303
+ display: inline-block;
304
+ margin-bottom: 0;
305
+ margin-right: 15px;
306
+ }
307
+ .module-header .details .module-info-basic > div {
308
+ padding-bottom: 0.35em;
309
+ }
310
+ .module-header .details .module-info-basic ul {
311
+ margin: 0;
312
+ list-style-type: none;
313
+ }
314
+ .module-header .details .module-info-basic ul.release-os-compat li {
315
+ display: inline;
316
+ margin-right: 5px;
317
+ }
318
+ .module-header .details .module-info-basic ul.release-os-compat span[data-releases] {
319
+ border-bottom: 1px dotted;
320
+ cursor: default;
321
+ }
322
+ .module-header .details .module-info-basic .module-info-summary {
323
+ margin-bottom: 1em;
324
+ }
325
+ .module-header .details .module-info-basic .module-info-tags {
326
+ font-size: 0.85em;
327
+ margin-top: 1.75em;
328
+ width: 85%;
329
+ }
330
+ .module-header .details .module-info-basic .compatibility {
331
+ background-color: #ffffff;
332
+ padding: 0.5em;
333
+ margin-top: 0.25em;
334
+ }
335
+ .module-header .details .module-info-basic .compatibility ul.bullets {
336
+ list-style-type: disc;
337
+ margin-left: 1.5em;
338
+ }
339
+ .module-header .details .module-info-basic .compatibility ul.bullets li {
340
+ margin-bottom: 0;
341
+ padding-bottom: 0;
342
+ }
343
+ .module-header .download-info {
344
+ padding-top: 1em;
345
+ margin-top: 1em;
346
+ border-top: 1px #ccc solid;
347
+ }
348
+ .module-header .download-info > div {
349
+ -moz-box-sizing: border-box;
350
+ box-sizing: border-box;
351
+ }
352
+ .module-header .download-info .installation {
353
+ float: left;
354
+ width: 75%;
355
+ }
356
+ .module-header .download-info .installation small {
357
+ display: block;
358
+ float: left;
359
+ width: 50%;
360
+ font-size: 11px;
361
+ }
362
+ .module-header .download-info .installation small.download-link {
363
+ text-align: right;
364
+ font-weight: bold;
365
+ }
366
+ .module-header .download-info .download-counts {
367
+ float: left;
368
+ width: 25%;
369
+ padding-top: 36px;
370
+ padding-right: 5%;
371
+ text-align: right;
372
+ font-size: 1.1em;
373
+ line-height: 1em;
374
+ font-weight: bold;
375
+ }
376
+ .module-header .download-info .download-counts small {
377
+ font-size: 11px;
378
+ font-weight: normal;
379
+ color: #6c6d6d;
380
+ }
381
+ .module-header .download-info .pe-only {
382
+ padding-left: 93px;
383
+ }
384
+ .module-header .download-info .pe-only input[type=text] {
385
+ box-sizing: border-box;
386
+ max-width: none;
387
+ width: 100%;
388
+ }
389
+ .module-header .download-info .pe-only p {
390
+ margin-bottom: 0.5em;
391
+ }
392
+ .module-header-sidebar {
393
+ float: right;
394
+ width: 22%;
395
+ }
396
+ .module-meta-info ul.release-dependencies {
397
+ margin-top: 1.25em;
398
+ }
399
+ #module-release-header {
400
+ overflow: auto;
401
+ margin-top: 20px;
402
+ margin-bottom: 10px;
403
+ }
404
+ #module-release-header #module-release-title {
405
+ float: left;
406
+ font-size: 1.2em;
407
+ }
408
+ #module-release-header #module-release-switcher {
409
+ float: right;
410
+ padding-top: 3px;
411
+ text-align: right;
412
+ font-size: 13px;
413
+ }
414
+ #module-release-header #module-release-switcher label {
415
+ display: inline-block;
416
+ font-weight: normal;
417
+ }
418
+ #module-release-header #module-release-switcher a {
419
+ display: inline-block;
420
+ margin-left: 6px;
421
+ padding: 3px 9px;
422
+ min-width: 60px;
423
+ border-radius: 4px;
424
+ background-color: #f4f4f4;
425
+ text-align: center;
426
+ }
218
427
  ul, ol, dl {
219
428
  margin-bottom: 1.5em;
220
429
  margin-left: 0;
@@ -249,6 +458,11 @@ li.private {
249
458
  background-repeat: no-repeat;
250
459
  background-position: right top;
251
460
  }
461
+ section.private {
462
+ background-image: url("/img/endorsement-private.png");
463
+ background-repeat: no-repeat;
464
+ background-position: right top;
465
+ }
252
466
  p {
253
467
  margin: 0;
254
468
  }
@@ -277,3 +491,25 @@ a.module-link {
277
491
  color: #0095dd;
278
492
  font-size: 0.9em;
279
493
  }
494
+ .installation input.paste-code {
495
+ display: block;
496
+ -moz-box-sizing: border-box;
497
+ box-sizing: border-box;
498
+ margin-top: 0.5em;
499
+ margin-bottom: 3px;
500
+ width: 100%;
501
+ max-width: none;
502
+ padding: 0.75em;
503
+ border: 0;
504
+ background: #e5e5e5;
505
+ color: #5d5e59;
506
+ font-family: Monaco, "Liberation Mono", Courier, monospace;
507
+ }
508
+ pre {
509
+ border-radius: .25em;
510
+ background: #f5f2f0;
511
+ border: 1px solid #DDD;
512
+ padding: .5em 1em;
513
+ overflow: auto;
514
+ display: block;
515
+ }
@@ -61,4 +61,4 @@
61
61
  .side-width.clearfix
62
62
  = yield
63
63
  %script{ :src => 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js' }
64
- %script{ :src => 'js/internal.js' }
64
+ %script{ :src => 'js/internal.js' }
@@ -0,0 +1,71 @@
1
+ -# -*- encoding: utf-8 -*-
2
+ -#
3
+ -# Copyright 2015 North Development AB
4
+ -#
5
+ -# Licensed under the Apache License, Version 2.0 (the "License");
6
+ -# you may not use this file except in compliance with the License.
7
+ -# You may obtain a copy of the License at
8
+ -#
9
+ -# http://www.apache.org/licenses/LICENSE-2.0
10
+ -#
11
+ -# Unless required by applicable law or agreed to in writing, software
12
+ -# distributed under the License is distributed on an "AS IS" BASIS,
13
+ -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ -# See the License for the specific language governing permissions and
15
+ -# limitations under the License.
16
+
17
+ - if !module_metadata.has_key? 'metadata'
18
+ %section{:id => 'content'}
19
+ %div{:class => 'site-width clearfix'}
20
+ %section{:id => 'body', :class => ' '}
21
+ No such module
22
+ - else
23
+ %section{:id => 'content'}
24
+ %div{:class => 'site-width clearfix'}
25
+ %section{:id => 'body', :class => ' '}
26
+ %div{:class => 'module-header-container clearfix'}
27
+ %section{:class => module_metadata['private'] ? 'module-header private' : 'module-header'}
28
+ %section{:class => 'details clearfix'}
29
+ %div{:class => 'module-info-basic'}
30
+ %div{:class => 'module-info-header'}
31
+ %h2
32
+ %span{:class => 'namespace'}= module_metadata['metadata']['name']
33
+ %div{:class => 'module-info-author'}= "by: #{module_metadata['metadata']['author']}"
34
+ %ul{:class => 'module-links'}
35
+ %li
36
+ %a{:href => module_metadata['metadata']['project_page']}= 'Project URL'
37
+ %li
38
+ %a{:href => module_metadata['metadata']['issues_url']}= 'Report issues'
39
+ %div{:class => 'module-info-summary'}= module_metadata['metadata']['summary']
40
+ %div{:class => 'download-info clearfix'}
41
+ %div{:class => 'installation'}
42
+ %div{:class => 'pmt-option clearfix'}
43
+ %strong= 'Use this command to install the latest compatible version:'
44
+ %input{:type => 'text', :class => 'paste-code', :value => "puppet module install --module_repository=#{base_url} #{module_metadata['metadata']['name']}", :onclick => 'this.select()'}
45
+ %div{:class => 'module-meta-info clearfix'}
46
+ %h3= 'Module dependencies'
47
+ %ul.release-dependencies
48
+ - module_metadata['metadata']['dependencies'].each do |dep|
49
+ %li
50
+ %a{:href => "/module?name=#{dep['name']}"}= dep['name']
51
+ - if dep['version_requirement']
52
+ = "(#{dep['version_requirement']})"
53
+ %section{:id => 'module-release-info'}
54
+ %div
55
+ %div{:id => 'module-release-header'}
56
+ %div{:id => 'module-release-title'}
57
+ Version
58
+ %strong= module_metadata['metadata']['version']
59
+ %div{:id => 'module-release-switcher'}
60
+ %label= 'Select another release: '
61
+ %select{:id => 'module-release-selector', :onchange => "location = this.options[this.selectedIndex].value;"}
62
+ - releases.each do |release|
63
+ %option{:value => "/module?name=#{module_metadata['metadata']['name']}&version=#{release['version']}", :selected => module_metadata['metadata']['version'] == release['version']}= release['version']
64
+ %a{:class => 'module-release-download', :href => module_metadata['file_uri'], :title => 'Download module'}= 'Download'
65
+ %div{:id => 'release-info-tabs', :class => 'module-meta-info'}
66
+ %div{:class => 'tabbed content'}
67
+ %div
68
+ %div
69
+ %section{:class => 'markdown'}
70
+ :preserve
71
+ #{readme_markdown}