puppet-forge-server 1.8.0 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
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}