Skip to content

Commit 6ff3ef4

Browse files
committed
Merge pull request #65 from allegro/development
basic auth/github token support
2 parents 46de9f1 + ac590ca commit 6ff3ef4

File tree

11 files changed

+179
-10
lines changed

11 files changed

+179
-10
lines changed

docs/changelog.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
Changelog
22
=========
33

4+
* **1.2.3** (29.03.2015)
5+
* support for Basic Auth username and password (GitHub tokens!)
46
* **1.2.2** (21.03.2015)
57
* use newer GrGit (and JGit) version with some bugfixes
68
* start using Coveralls

docs/configuration/authorization.rst

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ All interactive authorization mechanisms are provided by `grgit <https://github.
88
see `authorization docs <http://ajoberstar.org/grgit/docs/groovydoc/org/ajoberstar/grgit/auth/AuthConfig.html>`_
99
for more information.
1010

11+
Interactive mode is default option, switched off by using any special properties described below.
12+
1113
SSH Key/password
1214
----------------
1315

@@ -51,3 +53,27 @@ dynamically using custom Gradle tasks right before release. To change credential
5153
task release {
5254
dependsOn loadKeyPassword
5355
}
56+
57+
58+
HTTP Basic Auth/GitHub tokens
59+
-----------------------------
60+
61+
Same as with SSH keys, ``axion-release-plugin``gives option to set basic auth data when connecting to repository via
62+
HTTP. This is especially useful when using `GitHub OAuth tokens <https://help.github.com/articles/git-automation-with-oauth-tokens/>`_.
63+
64+
Command line
65+
^^^^^^^^^^^^
66+
67+
Use ``release.customUsername`` and ``release.customPassword`` properties to set username and password that will be provided
68+
when using Basic Auth. If password is not set, it defaults to empty string.
69+
70+
Dynamic
71+
^^^^^^^
72+
73+
Username and password can be provided in runtime, just before push is made via ``scmVersion.repository.customUsername``
74+
and ``scmVersion.repository.customPassword`` properties::
75+
76+
77+
task loadGitHubToken << {
78+
scmVersion.repository.customUsername = loadGitHubTokenFromSomewhere()
79+
}

src/main/groovy/pl/allegro/tech/build/axion/release/domain/RepositoryConfig.groovy

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,8 @@ class RepositoryConfig {
1111
def customKey
1212

1313
String customKeyPassword
14+
15+
String customUsername
16+
17+
String customPassword = ''
1418
}

src/main/groovy/pl/allegro/tech/build/axion/release/domain/RepositoryConfigFactory.groovy

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ class RepositoryConfigFactory {
1010
private static final String CUSTOM_KEY_FILE_PROPERTY = 'release.customKeyFile'
1111

1212
private static final String CUSTOM_KEY_PASSWORD_PROPERTY = 'release.customKeyPassword'
13+
14+
private static final String USERNAME_PROPERTY = 'release.customUsername'
15+
16+
private static final String PASSWORD_PROPERTY = 'release.customPassword'
1317

1418

1519
static RepositoryConfig create(Project project) {
@@ -25,6 +29,14 @@ class RepositoryConfigFactory {
2529
} else if (project.hasProperty(CUSTOM_KEY_FILE_PROPERTY)) {
2630
config.customKey = FileLoader.readFrom(project.property(CUSTOM_KEY_FILE_PROPERTY))
2731
}
32+
33+
if(project.hasProperty(USERNAME_PROPERTY)) {
34+
config.customUsername = project.property(USERNAME_PROPERTY)
35+
}
36+
if(project.hasProperty(PASSWORD_PROPERTY)) {
37+
config.customPassword = project.property(PASSWORD_PROPERTY)
38+
}
39+
2840
return config
2941
}
3042
}

src/main/groovy/pl/allegro/tech/build/axion/release/domain/scm/ScmIdentity.groovy

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,27 @@ public class ScmIdentity {
77

88
final boolean useDefault
99

10+
final boolean privateKeyBased
11+
12+
final boolean usernameBased
13+
1014
final String privateKey
1115

1216
final String passPhrase
17+
18+
final String username
19+
20+
final String password
1321

1422
static ScmIdentity defaultIdentity() {
1523
return new ScmIdentity(useDefault: true)
1624
}
1725

18-
static ScmIdentity customIdentity(String privateKey, String passPhrase) {
19-
return new ScmIdentity(privateKey: privateKey, passPhrase: passPhrase, useDefault: false)
26+
static ScmIdentity keyIdentity(String privateKey, String passPhrase) {
27+
return new ScmIdentity(privateKey: privateKey, passPhrase: passPhrase, privateKeyBased: true, useDefault: false)
28+
}
29+
30+
static ScmIdentity usernameIdentity(String username, String password) {
31+
return new ScmIdentity(username: username, password: password, usernameBased: true, useDefault: false)
2032
}
2133
}

src/main/groovy/pl/allegro/tech/build/axion/release/domain/scm/ScmIdentityResolver.groovy

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ class ScmIdentityResolver {
88
static ScmIdentity resolve(RepositoryConfig config) {
99
ScmIdentity identity
1010
if (config.customKey) {
11-
identity = ScmIdentity.customIdentity(FileLoader.readIfFile(config.customKey), config.customKeyPassword)
11+
identity = ScmIdentity.keyIdentity(FileLoader.readIfFile(config.customKey), config.customKeyPassword)
12+
} else if (config.customUsername) {
13+
identity = ScmIdentity.usernameIdentity(config.customUsername, config.customPassword)
1214
} else {
1315
identity = ScmIdentity.defaultIdentity()
1416
}

src/main/groovy/pl/allegro/tech/build/axion/release/infrastructure/git/GitRepository.groovy

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ class GitRepository implements ScmRepository {
2222

2323
private static final String GIT_TAG_PREFIX = 'refs/tags/'
2424

25+
private final TransportConfigFactory transportConfigFactory = new TransportConfigFactory()
26+
2527
private final File repositoryDir
2628

2729
private final Grgit repository
@@ -100,13 +102,7 @@ class GitRepository implements ScmRepository {
100102
}
101103

102104
private void setTransportOptions(ScmIdentity identity, TransportCommand command) {
103-
command.transportConfigCallback = new TransportConfigCallback() {
104-
@Override
105-
void configure(Transport transport) {
106-
SshTransport sshTransport = (SshTransport) transport
107-
sshTransport.setSshSessionFactory(new SshConnector(identity))
108-
}
109-
}
105+
command.transportConfigCallback = transportConfigFactory.create(identity)
110106
}
111107

112108
@Override
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package pl.allegro.tech.build.axion.release.infrastructure.git
2+
3+
import org.eclipse.jgit.errors.UnsupportedCredentialItem
4+
import org.eclipse.jgit.transport.CredentialItem
5+
import org.eclipse.jgit.transport.CredentialsProvider
6+
import org.eclipse.jgit.transport.URIish
7+
8+
class SimpleCredentialsProvider extends CredentialsProvider {
9+
10+
private final String username
11+
12+
private final String password
13+
14+
SimpleCredentialsProvider(String username, String password) {
15+
this.username = username
16+
this.password = password
17+
}
18+
19+
@Override
20+
boolean isInteractive() {
21+
return false
22+
}
23+
24+
@Override
25+
boolean supports(CredentialItem... items) {
26+
items.every { it instanceof CredentialItem.Username || it instanceof CredentialItem.Password }
27+
}
28+
29+
@Override
30+
boolean get(URIish uri, CredentialItem... items) throws UnsupportedCredentialItem {
31+
items.each {
32+
if(it instanceof CredentialItem.Username) {
33+
it.setValue(username)
34+
}
35+
else if (it instanceof CredentialItem.Password) {
36+
it.setValue(password.toCharArray())
37+
}
38+
}
39+
}
40+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package pl.allegro.tech.build.axion.release.infrastructure.git
2+
3+
import org.eclipse.jgit.api.TransportConfigCallback
4+
import org.eclipse.jgit.transport.SshTransport
5+
import org.eclipse.jgit.transport.Transport
6+
import pl.allegro.tech.build.axion.release.domain.scm.ScmIdentity
7+
8+
class TransportConfigFactory {
9+
10+
TransportConfigCallback create(ScmIdentity identity) {
11+
if (identity.privateKeyBased) {
12+
return createForSsh(identity)
13+
} else if (identity.usernameBased) {
14+
return createForUsername(identity)
15+
}
16+
throw new IllegalArgumentException("Transport callback can be created only for private key or username based identity")
17+
}
18+
19+
private TransportConfigCallback createForSsh(ScmIdentity identity) {
20+
return new TransportConfigCallback() {
21+
@Override
22+
void configure(Transport transport) {
23+
SshTransport sshTransport = (SshTransport) transport
24+
sshTransport.setSshSessionFactory(new SshConnector(identity))
25+
}
26+
}
27+
}
28+
29+
private TransportConfigCallback createForUsername(ScmIdentity identity) {
30+
return new TransportConfigCallback() {
31+
@Override
32+
void configure(Transport transport) {
33+
transport.setCredentialsProvider(new SimpleCredentialsProvider(identity.username, identity.password))
34+
}
35+
}
36+
}
37+
}

src/test/groovy/pl/allegro/tech/build/axion/release/domain/RepositoryConfigFactoryTest.groovy

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class RepositoryConfigFactoryTest extends Specification {
2727
then:
2828
!config.customKeyPassword
2929
!config.customKey
30+
!config.customUsername
31+
config.customPassword == ''
3032
}
3133

3234
def "should set authorization options when custom key and password provided"() {
@@ -80,5 +82,19 @@ class RepositoryConfigFactoryTest extends Specification {
8082
then:
8183
config.customKey == 'key'
8284
}
85+
86+
def "should set username and password when provided via 'release.customUsername' and 'release.customPassword'"() {
87+
given:
88+
Project project = ProjectBuilder.builder().build()
89+
project.extensions.extraProperties.set('release.customUsername', 'username')
90+
project.extensions.extraProperties.set('release.customPassword', 'password')
91+
92+
when:
93+
RepositoryConfig config = RepositoryConfigFactory.create(project)
94+
95+
then:
96+
config.customUsername == 'username'
97+
config.customPassword == 'password'
98+
}
8399

84100
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package pl.allegro.tech.build.axion.release.infrastructure.git
2+
3+
import org.eclipse.jgit.transport.CredentialItem
4+
import spock.lang.Specification
5+
6+
class SimpleCredentialsProviderTest extends Specification {
7+
8+
def "should provide username and password"() {
9+
given:
10+
SimpleCredentialsProvider provider = new SimpleCredentialsProvider('username', 'password')
11+
CredentialItem.Password passwordItem = new CredentialItem.Password('whatever')
12+
CredentialItem.Username usernameItem = new CredentialItem.Username()
13+
14+
when:
15+
provider.get(null, passwordItem, usernameItem)
16+
17+
then:
18+
usernameItem.value == 'username'
19+
passwordItem.value == 'password'.toCharArray()
20+
}
21+
22+
}

0 commit comments

Comments
 (0)