Skip to content

Commit 79f3fa7

Browse files
authored
Merge pull request #6 from buildkite-plugins/feat/artifactory_SUP-4303
Add support for JFrog Artifactory
2 parents 04a59f1 + e7c39eb commit 79f3fa7

File tree

11 files changed

+274
-71
lines changed

11 files changed

+274
-71
lines changed

README.md

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Supported providers:
66
- Amazon Elastic Container Registry (ECR)
77
- Google Artifact Registry (GAR)
88
- Buildkite Packages Container Registry
9+
- Artifactory Docker Registry
910

1011
## Options
1112

@@ -15,7 +16,7 @@ These are all the options available to configure this plugin's behaviour.
1516

1617
#### `provider` (string)
1718

18-
The registry provider to use. Supported values: `ecr`, `gar`, `buildkite`.
19+
The registry provider to use. Supported values: `ecr`, `gar`, `buildkite`, `artifactory`.
1920

2021
#### `image` (string)
2122

@@ -82,6 +83,22 @@ Authentication method to use. Supported values: `api-token`, `oidc`.
8283

8384
The Buildkite API token with Read Packages and Write Packages scopes. Required when `auth-method` is `api-token`. Can also be provided via the `BUILDKITE_API_TOKEN` environment variable for backward compatibility.
8485

86+
### Artifactory Provider Options
87+
88+
**Note:** Authentication requires a username (typically email) and identity token from your Artifactory instance.
89+
90+
#### `registry-url` (string)
91+
92+
The Artifactory registry URL (e.g., `myjfroginstance.jfrog.io`). Do not include the protocol (`https://`).
93+
94+
#### `username` (string)
95+
96+
The username for Artifactory authentication, typically your email address.
97+
98+
#### `identity-token` (string)
99+
100+
The Artifactory identity token for authentication. Can reference an environment variable using `$VARIABLE_NAME` syntax.
101+
85102
## Examples
86103

87104
### Push to Amazon ECR
@@ -92,7 +109,7 @@ This example pushes an image to an ECR repository.
92109
steps:
93110
- label: ":docker: Build and Push"
94111
plugins:
95-
- docker-image-push#v1.0.0:
112+
- docker-image-push#v1.0.1:
96113
provider: ecr
97114
image: my-app
98115
ecr:
@@ -108,7 +125,7 @@ This example pushes an image to a GAR repository with a specific tag.
108125
steps:
109126
- label: ":docker: Build and Push"
110127
plugins:
111-
- docker-image-push#v1.0.0:
128+
- docker-image-push#v1.0.1:
112129
provider: gar
113130
image: my-app
114131
tag: "v1.2.3"
@@ -152,6 +169,24 @@ steps:
152169
auth-method: oidc
153170
```
154171
172+
### Push to Artifactory Docker Registry
173+
174+
This example pushes an image to an Artifactory Docker registry.
175+
176+
```yaml
177+
steps:
178+
- label: ":docker: Build and Push"
179+
plugins:
180+
- docker-image-push#v1.0.1:
181+
provider: artifactory
182+
image: my-app
183+
tag: "v1.2.3"
184+
artifactory:
185+
registry-url: myjfroginstance.jfrog.io
186+
username: me@example.com
187+
identity-token: $ARTIFACTORY_IDENTITY_TOKEN
188+
```
189+
155190
### Verbose Mode
156191
157192
Enable verbose mode for detailed debug output.
@@ -160,7 +195,7 @@ Enable verbose mode for detailed debug output.
160195
steps:
161196
- label: ":docker: Build and Push (Debug)"
162197
plugins:
163-
- docker-image-push#v1.0.0:
198+
- docker-image-push#v1.0.1:
164199
provider: ecr
165200
image: my-app
166201
verbose: true

hooks/environment

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
set -euo pipefail
33

44
# Enable debug mode if requested
5-
if [[ "${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_VERBOSE:-false}" =~ (true|on|1) ]] ; then
5+
if [[ "${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_VERBOSE:-false}" =~ (true|on|1) ]]; then
66
echo "~~~ :hammer: Enabling debug mode"
77
set -x
88
fi
@@ -32,13 +32,12 @@ main() {
3232
log_info "Image - $image"
3333

3434
case "$provider" in
35-
ecr|gar|buildkite)
36-
;;
37-
*)
38-
log_error "unsupported provider '$provider'"
39-
log_info "Supported providers: ecr, gar, buildkite"
40-
exit 1
41-
;;
35+
ecr | gar | buildkite | artifactory) ;;
36+
*)
37+
log_error "unsupported provider '$provider'"
38+
log_info "Supported providers: ecr, gar, buildkite, artifactory"
39+
exit 1
40+
;;
4241
esac
4342

4443
# Authenticate with registry

hooks/post-command

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
set -euo pipefail
33

44
# Enable debug mode if requested
5-
if [[ "${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_VERBOSE:-false}" =~ (true|on|1) ]] ; then
5+
if [[ "${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_VERBOSE:-false}" =~ (true|on|1) ]]; then
66
echo "~~~ :hammer: Enabling debug mode"
77
set -x
88
fi

lib/plugin.bash

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,27 @@ source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/providers/ecr.bash"
1111
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/providers/gar.bash"
1212
# shellcheck source=lib/providers/buildkite.bash
1313
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/providers/buildkite.bash"
14+
# shellcheck source=lib/providers/artifactory.bash
15+
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/providers/artifactory.bash"
1416

1517
setup_provider_environment() {
1618
local provider="$1"
1719

1820
case "$provider" in
19-
ecr)
20-
setup_ecr_environment
21-
;;
22-
gar)
23-
setup_gar_environment
24-
;;
25-
buildkite)
26-
setup_buildkite_environment
27-
;;
28-
*)
29-
unknown_provider "$provider"
30-
;;
21+
ecr)
22+
setup_ecr_environment
23+
;;
24+
gar)
25+
setup_gar_environment
26+
;;
27+
buildkite)
28+
setup_buildkite_environment
29+
;;
30+
artifactory)
31+
setup_artifactory_environment
32+
;;
33+
*)
34+
unknown_provider "$provider"
35+
;;
3136
esac
3237
}

lib/providers/artifactory.bash

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/bin/bash
2+
3+
setup_artifactory_environment() {
4+
local registry_url_raw="${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_ARTIFACTORY_REGISTRY_URL:-}"
5+
local username_raw="${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_ARTIFACTORY_USERNAME:-}"
6+
local identity_token_raw="${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_ARTIFACTORY_IDENTITY_TOKEN:-}"
7+
8+
# Validate required parameters
9+
if [[ -z "$registry_url_raw" ]]; then
10+
log_error "Artifactory registry URL is required"
11+
log_info "Set it via the 'registry-url' parameter in artifactory configuration"
12+
exit 1
13+
fi
14+
15+
if [[ -z "$username_raw" ]]; then
16+
log_error "Artifactory username is required"
17+
log_info "Set it via the 'username' parameter in artifactory configuration"
18+
exit 1
19+
fi
20+
21+
if [[ -z "$identity_token_raw" ]]; then
22+
log_error "Artifactory identity token is required"
23+
log_info "Set it via the 'identity-token' parameter in artifactory configuration"
24+
exit 1
25+
fi
26+
27+
# Process environment variable references in parameters
28+
local registry_url
29+
registry_url=$(expand_env_var "$registry_url_raw" "registry-url")
30+
31+
local username
32+
username=$(expand_env_var "$username_raw" "username")
33+
34+
local identity_token
35+
identity_token=$(expand_env_var "$identity_token_raw" "identity-token")
36+
37+
# Clean up registry URL (remove protocol if present)
38+
registry_url="${registry_url#https://}"
39+
registry_url="${registry_url#http://}"
40+
41+
export DOCKER_PUSH_ARTIFACTORY_REGISTRY_URL="$registry_url"
42+
43+
log_info "Artifactory registry URL: $registry_url"
44+
log_info "Artifactory username: $username"
45+
46+
log_info "Authenticating with Artifactory Docker registry..."
47+
if docker login "$registry_url" -u "$username" -p "$identity_token"; then
48+
log_success "Successfully authenticated with Artifactory"
49+
else
50+
log_error "Failed to authenticate with Artifactory"
51+
log_info "Verify your username and identity token are correct"
52+
log_info "Ensure the registry URL is accessible and supports Docker registry API"
53+
exit 1
54+
fi
55+
56+
local repository="${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_ARTIFACTORY_REPOSITORY:-${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_IMAGE}}"
57+
local tag="${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_TAG:-latest}"
58+
export DOCKER_PUSH_REMOTE_IMAGE="${registry_url}/${repository}/${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_IMAGE}:${tag}"
59+
}

lib/providers/buildkite.bash

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,17 @@ setup_buildkite_environment() {
3131

3232
# Authenticate with registry based on method
3333
case "$auth_method" in
34-
api-token)
35-
authenticate_with_api_token "$registry_url"
36-
;;
37-
oidc)
38-
authenticate_with_oidc "$registry_url"
39-
;;
40-
*)
41-
log_error "Unsupported authentication method: $auth_method"
42-
log_info "Supported methods: api-token, oidc"
43-
exit 1
44-
;;
34+
api-token)
35+
authenticate_with_api_token "$registry_url"
36+
;;
37+
oidc)
38+
authenticate_with_oidc "$registry_url"
39+
;;
40+
*)
41+
log_error "Unsupported authentication method: $auth_method"
42+
log_info "Supported methods: api-token, oidc"
43+
exit 1
44+
;;
4545
esac
4646

4747
local tag="${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_TAG:-latest}"
@@ -51,18 +51,18 @@ setup_buildkite_environment() {
5151
authenticate_with_api_token() {
5252
local registry_url="$1"
5353
local api_token_raw="${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_BUILDKITE_API_TOKEN:-}"
54-
54+
5555
local api_token
5656
# Restrict environment variable expansion to safe, allow listed variables only
5757
# shellcheck disable=SC2016
5858
case "${api_token_raw}" in
59-
'$CONTAINER_PACKAGE_REGISTRY_TOKEN'|'$BUILDKITE_API_TOKEN'|'$BUILDKITE_PLUGIN_'*)
60-
local var_name="${api_token_raw#$}"
61-
api_token="${!var_name}"
62-
;;
63-
*)
64-
api_token="${api_token_raw}"
65-
;;
59+
'$CONTAINER_PACKAGE_REGISTRY_TOKEN' | '$BUILDKITE_API_TOKEN' | '$BUILDKITE_PLUGIN_'*)
60+
local var_name="${api_token_raw#$}"
61+
api_token="${!var_name}"
62+
;;
63+
*)
64+
api_token="${api_token_raw}"
65+
;;
6666
esac
6767

6868
# Fallback to environment variable for backward compatibility
@@ -90,7 +90,7 @@ authenticate_with_api_token() {
9090
authenticate_with_oidc() {
9191
local registry_url="$1"
9292
local audience="https://${registry_url}"
93-
93+
9494
log_info "Requesting OIDC token for audience: $audience"
9595
log_info "Authenticating with Buildkite Packages using OIDC..."
9696

@@ -101,4 +101,4 @@ authenticate_with_oidc() {
101101
log_info "Verify your pipeline has access to the registry and meets OIDC policy requirements"
102102
exit 1
103103
fi
104-
}
104+
}

lib/providers/ecr.bash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,6 @@ setup_ecr_environment() {
4444

4545
log_success "Successfully authenticated with ECR"
4646

47-
local tag="${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_TAG:-latest}"
47+
local tag="${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_TAG:-latest}"
4848
export DOCKER_PUSH_REMOTE_IMAGE="${registry_url}/${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_IMAGE}:${tag}"
4949
}

lib/providers/gar.bash

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,3 @@ setup_gar_environment() {
4141

4242
export DOCKER_PUSH_REMOTE_IMAGE="${registry_host}/${project}/${repository}/${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_IMAGE}:${tag}"
4343
}
44-
45-

lib/shared.bash

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,37 @@ log_error() {
2020
echo "[ERROR]: $*" >&2
2121
}
2222

23+
# Expand environment variables from plugin configuration values
24+
# Usage: expand_env_var "raw_value" "parameter_name"
25+
# Returns: expanded value or exits with error if variable is missing/empty
26+
expand_env_var() {
27+
local raw_value="$1"
28+
local param_name="$2"
29+
local result
30+
31+
# shellcheck disable=SC2016
32+
case "${raw_value}" in
33+
'$'*)
34+
local var_name="${raw_value#$}"
35+
if [[ -v "${var_name}" ]]; then
36+
result="${!var_name}"
37+
if [[ -z "$result" ]]; then
38+
log_error "Environment variable '${var_name}' referenced by ${param_name} parameter is empty or not set"
39+
exit 1
40+
fi
41+
else
42+
log_error "Environment variable '${var_name}' referenced by ${param_name} parameter is empty or not set"
43+
exit 1
44+
fi
45+
;;
46+
*)
47+
result="${raw_value}"
48+
;;
49+
esac
50+
51+
echo "$result"
52+
}
53+
2354
command_exists() {
2455
command -v "$1" >/dev/null 2>&1
2556
}
@@ -37,20 +68,20 @@ check_dependencies() {
3768
fi
3869

3970
case "${BUILDKITE_PLUGIN_DOCKER_IMAGE_PUSH_PROVIDER}" in
40-
ecr)
41-
if ! command_exists aws; then
42-
missing_deps+=("aws")
43-
fi
44-
;;
45-
gar)
46-
if ! command_exists gcloud; then
47-
missing_deps+=("gcloud")
48-
fi
49-
;;
50-
buildkite)
51-
# No additional CLI dependencies required for Buildkite Packages
52-
# buildkite-agent is always available in Buildkite pipeline jobs
53-
;;
71+
ecr)
72+
if ! command_exists aws; then
73+
missing_deps+=("aws")
74+
fi
75+
;;
76+
gar)
77+
if ! command_exists gcloud; then
78+
missing_deps+=("gcloud")
79+
fi
80+
;;
81+
buildkite)
82+
# No additional CLI dependencies required for Buildkite Packages
83+
# buildkite-agent is always available in Buildkite pipeline jobs
84+
;;
5485
esac
5586

5687
if [[ ${#missing_deps[@]} -gt 0 ]]; then
@@ -60,8 +91,6 @@ check_dependencies() {
6091
fi
6192
}
6293

63-
64-
6594
push_image() {
6695
local local_image="$1"
6796
local remote_image="${DOCKER_PUSH_REMOTE_IMAGE:-}"

0 commit comments

Comments
 (0)