jara 1.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e617ac5c7fddb9396203f924042e6acf558ef7a0
4
+ data.tar.gz: 46aa05ca9134886f3c516f04ab0005b42d97cc89
5
+ SHA512:
6
+ metadata.gz: 40091d005522a32a2e9553dba4c05a92b7acc454201db58dbf3565b711a271abed9bd4be2b4fca92b671197621261667be8c333e02baba888c862768ebd74ca1
7
+ data.tar.gz: 28e9e8589c1b5dfae7631df23be94fab4765048a6a1e78927f7c4f6f1a2d3822bccdd44dbb6fc3507c350a22b43bba2ac78baeef2e323d86a0109a7dee0db4bb
data/LICENSE.txt ADDED
@@ -0,0 +1,12 @@
1
+ Copyright (c) 2014, Burt AB
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
+
6
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7
+
8
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9
+
10
+ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # Jarå
2
+
3
+ Jarå builds self-contained JARs of JRuby applications and publishes them to S3. It will check that you've pushed your code, check out a pristine copy from git, build a JAR and upload it to S3.
4
+
5
+ # Usage
6
+
7
+ ```
8
+ # this will build an artifact from master and upload it to
9
+ # the "artifact-bucket" on S3
10
+ releaser = Jarå::Releaser.new('production', 'artifact-bucket')
11
+ releaser.release
12
+ ```
13
+
14
+ The JAR artifact will be named from the project name, environment, date stamp and commit SHA, and will be uploaded with a path on S3 that also contains the environment and project name. The name of the directory that contains the code is assumed to be the project name.
15
+
16
+ For example, if you run it from a directory called "foo_bar" and sets the environment "production" it will build the artifact "foo_bar-production-YYYYmmddHHMMSS-XXXXXXXX.jar", where "YYYYmmddHHMMSS" is the current date and time and "XXXXXXXX" is the first 8 characters from the commit SHA. The artifact will be cached locally in a directory called "build/production" and then uploaded to S3 into the specified bucket, with the key "production/foo_bar/foo_bar-production-YYYYmmddHHMMSS-XXXXXXXX.jar".
17
+
18
+ If you change "production" to "staging" it will build an artifact from the staging branch instead (and all other paths and names will have "staging" where they had "production" in the description above).
19
+
20
+ You may have noticed that specifying "production" created an artifact from the master branch, and "staging" used the staging branch. Using anything but "production" means that the branch name is assumed to be the same as the environment.
21
+
22
+ Before the artifact is built Jarå will check that _branch_name_ and origin/*branch_name* point to the same commit. The reason for this is so that you don't release an artifact with a SHA that is not visible to others (this does not check that you've pulled before you release, but the important thing is to not release something that is not trackable).
23
+
24
+ # Copyright
25
+
26
+ © 2014 Burt AB, see LICENSE.txt (BSD 3-Clause).
@@ -0,0 +1,179 @@
1
+ # encoding: utf-8
2
+
3
+ require 'tmpdir'
4
+ require 'fileutils'
5
+ require 'pathname'
6
+ require 'puck'
7
+ require 'digest/md5'
8
+ require 'aws-sdk-core'
9
+ require 'socket'
10
+
11
+
12
+ module Jara
13
+ ExecError = Class.new(JaraError)
14
+
15
+ class Releaser
16
+ def initialize(environment, bucket_name, options={})
17
+ @environment = environment
18
+ @bucket_name = bucket_name
19
+ @shell = options[:shell] || Shell.new
20
+ @archiver = options[:archiver] || Archiver.new
21
+ @file_system = options[:file_system] || FileUtils
22
+ @s3 = options[:s3]
23
+ @logger = options[:logger] || IoLogger.new($stderr)
24
+ @branch = @environment == 'production' ? 'master' : @environment
25
+ end
26
+
27
+ def build_artifact
28
+ if @environment.nil?
29
+ jar_name = "#{app_name}.jar"
30
+ Dir.chdir(project_dir) do
31
+ @archiver.create(jar_name: jar_name)
32
+ end
33
+ @logger.info('Created test artifact')
34
+ File.join(project_dir, 'build', jar_name)
35
+ elsif (artifact_path = find_local_artifact)
36
+ @logger.warn('An artifact for %s already exists: %s' % [branch_sha[0, 8], File.basename(artifact_path)])
37
+ artifact_path
38
+ else
39
+ date_stamp = Time.now.utc.strftime('%Y%m%d%H%M%S')
40
+ destination_dir = File.join(project_dir, 'build', @environment)
41
+ jar_name = [app_name, @environment, date_stamp, branch_sha[0, 8]].join('-') << '.jar'
42
+ Dir.mktmpdir do |path|
43
+ Dir.chdir(path) do
44
+ @shell.exec('git clone %s . && git checkout %s' % [project_dir, branch_sha])
45
+ @logger.info('Checked out %s from branch %s' % [branch_sha[0, 8], @branch])
46
+ @archiver.create(jar_name: jar_name)
47
+ @file_system.mkdir_p(destination_dir)
48
+ @file_system.cp("build/#{jar_name}", destination_dir)
49
+ @logger.info('Created artifact %s' % jar_name)
50
+ end
51
+ end
52
+ File.join(destination_dir, jar_name)
53
+ end
54
+ end
55
+
56
+ def release
57
+ raise JaraError, 'No environment set' unless @environment
58
+ raise JaraError, 'No bucket name set' unless @bucket_name
59
+ if obj = find_remote_artifact
60
+ @logger.warn('An artifact for %s already exists: s3://%s/%s' % [branch_sha[0, 8], @bucket_name, obj.key])
61
+ else
62
+ local_path = find_local_artifact || build_artifact
63
+ upload_artifact(local_path)
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ JAR_CONTENT_TYPE = 'application/java-archive'
70
+
71
+ def s3
72
+ @s3 ||= Aws.s3
73
+ end
74
+
75
+ def app_name
76
+ File.basename(project_dir)
77
+ end
78
+
79
+ def project_dir
80
+ unless defined? @project_dir
81
+ Pathname.new(Dir.getwd).descend do |path|
82
+ if Dir.entries(path).include?('.git')
83
+ @project_dir = path
84
+ break
85
+ end
86
+ end
87
+ unless defined? @project_dir
88
+ raise JaraError, 'Could not find project directory'
89
+ end
90
+ end
91
+ @project_dir
92
+ end
93
+
94
+ def branch_sha
95
+ @branch_sha ||= begin
96
+ result = @shell.exec('git rev-parse %s && git rev-parse origin/%s' % [@branch, @branch])
97
+ local_sha, remote_sha = result.split("\n").take(2)
98
+ if local_sha == remote_sha
99
+ local_sha
100
+ else
101
+ raise JaraError, '%s and origin/%s are not in sync, did you forget to push?' % [@branch, @branch]
102
+ end
103
+ end
104
+ end
105
+
106
+ def metadata
107
+ {
108
+ 'packaged_by' => "#{ENV['USER']}@#{Socket.gethostname}",
109
+ 'sha' => branch_sha
110
+ }
111
+ end
112
+
113
+ def find_local_artifact
114
+ candidates = Dir[File.join(project_dir, 'build', @environment, '*.jar')]
115
+ candidates.select! { |path| path.include?(branch_sha[0, 8]) }
116
+ candidates.sort.last
117
+ end
118
+
119
+ def upload_artifact(local_path)
120
+ begin
121
+ remote_path = [@environment, app_name, File.basename(local_path)].join('/')
122
+ content_md5 = Digest::MD5.file(local_path).hexdigest
123
+ File.open(local_path, 'rb') do |io|
124
+ s3.put_object(
125
+ bucket: @bucket_name,
126
+ key: remote_path,
127
+ content_type: JAR_CONTENT_TYPE,
128
+ content_md5: content_md5,
129
+ metadata: metadata,
130
+ body: io,
131
+ )
132
+ end
133
+ @logger.info('Artifact uploaded to s3://%s/%s' % [@bucket_name, remote_path])
134
+ end
135
+ end
136
+
137
+ def find_remote_artifact
138
+ listing = s3.list_objects(bucket: @bucket_name, prefix: [@environment, app_name, "#{app_name}-#{@environment}-"].join('/'))
139
+ listing.contents.find { |obj| obj.key.include?(branch_sha[0, 8]) }
140
+ end
141
+
142
+ class Shell
143
+ def exec(command)
144
+ output = %x(#{command})
145
+ unless $?.success?
146
+ raise ExecError, %(Command `#{command}` failed with output: #{output})
147
+ end
148
+ output
149
+ end
150
+ end
151
+
152
+ class Archiver
153
+ def create(options)
154
+ Puck::Jar.new(options).create!
155
+ end
156
+ end
157
+ end
158
+
159
+ class IoLogger
160
+ def initialize(io)
161
+ @io = io
162
+ end
163
+
164
+ def info(msg)
165
+ @io.puts(msg)
166
+ end
167
+
168
+ def warn(msg)
169
+ @io.puts(msg)
170
+ end
171
+ end
172
+
173
+ class NullLogger
174
+ def info(*); end
175
+ def warn(*); end
176
+ end
177
+
178
+ NULL_LOGGER = NullLogger.new
179
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+
3
+ module Jara
4
+ VERSION = '1.0.0'.freeze
5
+ end
data/lib/jara.rb ADDED
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ module Jara
4
+ JaraError = Class.new(StandardError)
5
+ end
6
+
7
+ Jarå = Jara
8
+
9
+ require 'jara/releaser'
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jara
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: java
6
+ authors:
7
+ - Burt Platform Team
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - '>='
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ name: puck
20
+ prerelease: false
21
+ type: :runtime
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ name: aws-sdk-core
34
+ prerelease: false
35
+ type: :runtime
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Build self-contained JAR artifacts and publish them to S3
42
+ email:
43
+ - theo@burtcorp.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - LICENSE.txt
49
+ - README.md
50
+ - lib/jara.rb
51
+ - lib/jara/releaser.rb
52
+ - lib/jara/version.rb
53
+ homepage: http://github.com/burtcorp/jara
54
+ licenses:
55
+ - BSD-3-Clause
56
+ metadata: {}
57
+ post_install_message:
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - '>='
64
+ - !ruby/object:Gem::Version
65
+ version: 1.9.3
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ requirements: []
72
+ rubyforge_project:
73
+ rubygems_version: 2.2.2
74
+ signing_key:
75
+ specification_version: 4
76
+ summary: Builds and publishes JAR artifacts
77
+ test_files: []