Skip to content

Commit d52ece0

Browse files
committed
Merge remote-tracking branch 'upstream2/main' into add-download-config-option
2 parents 92e0085 + dac2b9d commit d52ece0

4 files changed

Lines changed: 119 additions & 27 deletions

File tree

README.md

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ For example, in the following configuration:
4545
steps:
4646
- label: "Triggering pipelines"
4747
plugins:
48-
- monorepo-diff#v1.5.1:
48+
- monorepo-diff#v1.5.2:
4949
diff: "git diff --name-only HEAD~1"
5050
watch:
5151
- path: "**/*"
@@ -78,7 +78,7 @@ This is a sub-section that provides configuration for running commands or trigge
7878
steps:
7979
- label: "Triggering pipelines"
8080
plugins:
81-
- monorepo-diff#v1.5.1:
81+
- monorepo-diff#v1.5.2:
8282
watch:
8383
- path: app/
8484
config:
@@ -109,7 +109,7 @@ steps:
109109
steps:
110110
- label: "Triggering pipelines with plugin"
111111
plugins:
112-
- monorepo-diff#v1.5.1:
112+
- monorepo-diff#v1.5.2:
113113
watch:
114114
- path: test/.buildkite/
115115
config: # Required [trigger step configuration]
@@ -138,7 +138,7 @@ The plugin supports conditional execution of pipeline steps using the `if` key,
138138
steps:
139139
- label: "Triggering pipelines with plugin"
140140
plugins:
141-
- monorepo-diff#v1.5.1:
141+
- monorepo-diff#v1.5.2:
142142
diff: git diff --name-only HEAD~1
143143
watch:
144144
- path: services/api
@@ -151,20 +151,20 @@ steps:
151151
if: build.tag != null
152152
```
153153

154-
In the example above,
154+
In the example above,
155+
155156
- The `deploy-api` trigger will only run on the main branch or branches matching `release/*`.
156157
- The `web deployment` command will run only if the build has a tag.
157158

158-
159159
#### `diff` (optional)
160160

161161
This will run the script provided to determine the folder changes.
162162
Depending on your use case, you may want to determine the point where the branch occurs
163-
https://stackoverflow.com/questions/1527234/finding-a-branch-point-with-git and perform a diff against the branch point.
163+
<https://stackoverflow.com/questions/1527234/finding-a-branch-point-with-git> and perform a diff against the branch point.
164164

165165
Default: `git diff --name-only HEAD~1`
166166

167-
#### Sample output:
167+
#### Sample output
168168

169169
```
170170
README.md
@@ -201,7 +201,7 @@ git diff --name-only "$LATEST_TAG"
201201
steps:
202202
- label: "Triggering pipelines"
203203
plugins:
204-
- monorepo-diff#v1.5.1:
204+
- monorepo-diff#v1.5.2:
205205
diff: "git diff --name-only HEAD~1"
206206
watch:
207207
- path: "bar-service/"
@@ -228,7 +228,7 @@ A default `config` to run if no paths are matched, the `config` key is not requi
228228
steps:
229229
- label: "Triggering pipelines"
230230
plugins:
231-
- monorepo-diff#v1.5.1:
231+
- monorepo-diff#v1.5.2:
232232
diff: "git diff --name-only HEAD~1"
233233
watch:
234234
- path: "bar-service/"
@@ -250,7 +250,7 @@ The object values provided in this configuration will be appended to `env` prope
250250
steps:
251251
- label: "Triggering pipelines"
252252
plugins:
253-
- monorepo-diff#v1.5.1:
253+
- monorepo-diff#v1.5.2:
254254
diff: "git diff --name-only HEAD~1"
255255
watch:
256256
- path: "foo-service/"
@@ -272,7 +272,7 @@ Add `log_level` property to set the log level. Supported log levels are `debug`
272272
steps:
273273
- label: "Triggering pipelines"
274274
plugins:
275-
- monorepo-diff#v1.5.1:
275+
- monorepo-diff#v1.5.2:
276276
diff: "git diff --name-only HEAD~1"
277277
log_level: "debug" # defaults to "info"
278278
watch:
@@ -327,7 +327,7 @@ By setting `wait` to `true`, the build will wait until the triggered pipeline bu
327327
steps:
328328
- label: "Triggering pipelines"
329329
plugins:
330-
- monorepo-diff#v1.5.1:
330+
- monorepo-diff#v1.5.2:
331331
diff: "git diff --name-only $(head -n 1 last_successful_build)"
332332
interpolation: false
333333
env:
@@ -382,7 +382,6 @@ Thanks to [@chronotc](https://github.com/chronotc) and [@adikari](https://github
382382

383383
MIT (see [LICENSE](LICENSE))
384384

385-
386385
## How to Contribute
387386

388387
Please read [contributing guide](https://github.com/buildkite-plugins/monorepo-diff-buildkite-plugin/blob/master/CONTRIBUTING.md).

hooks/command

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#!/usr/bin/env bash
22
set -euo pipefail
33

4+
executable="monorepo-diff-buildkite-plugin"
5+
executable_version_file="${executable}.version"
6+
47
check_cmd() {
58
command -v "$1" > /dev/null 2>&1
69
return $?
@@ -63,6 +66,27 @@ downloader() {
6366
fi
6467
}
6568

69+
get_latest_version() {
70+
local _repo="https://api.github.com/repos/buildkite-plugins/monorepo-diff-buildkite-plugin"
71+
local _version=""
72+
73+
if check_cmd curl; then
74+
_version=$(curl -s "${_repo}/releases/latest" | grep -oE '"tag_name": "v[0-9]+\.[0-9]+\.[0-9]+"' | cut -d'"' -f4)
75+
elif check_cmd wget; then
76+
_version=$(wget -qO- "${_repo}/releases/latest" | grep -oE '"tag_name": "v[0-9]+\.[0-9]+\.[0-9]+"' | cut -d'"' -f4)
77+
fi
78+
79+
if [[ "$_version" =~ ^v[0-9]+\.[0-9]+\.[0-9]+ ]]; then
80+
echo "${_version}"
81+
fi
82+
}
83+
84+
get_binary_version() {
85+
if [ -f "${executable_version_file}" ]; then
86+
cat "${executable_version_file}" | tr -d '\n'
87+
fi
88+
}
89+
6690
get_version() {
6791
local _plugin=${BUILDKITE_PLUGINS:-""}
6892
local _version=""
@@ -76,38 +100,60 @@ get_version() {
76100
else
77101
_version=""
78102
fi
79-
103+
80104
RETVAL="$_version"
81105
}
82106

83107
download_binary_and_run() {
84108
get_architecture || return 1
85109
local _arch="$RETVAL"
86-
local _executable="monorepo-diff-buildkite-plugin"
87110
local _repo="https://github.com/buildkite-plugins/monorepo-diff-buildkite-plugin"
88111

89112
get_version || return 1
90-
local _version="$RETVAL"
113+
local _specified_version="$RETVAL"
114+
local _latest_version=""
115+
local _binary_version=""
116+
local test_mode="${BUILDKITE_PLUGIN_MONOREPO_DIFF_BUILDKITE_PLUGIN_TEST_MODE:-false}"
117+
local _url=""
91118

92-
if [ -z "${_version}" ]; then
93-
_url=${_repo}/releases/latest/download/${_executable}_${_arch}
94-
else
95-
_url=${_repo}/releases/download/${_version}/${_executable}_${_arch}
119+
if check_cmd "./${executable}"; then
120+
_binary_version=$(get_binary_version)
121+
if [[ -z "$_binary_version" ]]; then
122+
say "Warning: Could not determine binary version, will download fresh copy"
123+
fi
96124
fi
97125

98-
local test_mode="${BUILDKITE_PLUGIN_MONOREPO_DIFF_BUILDKITE_PLUGIN_TEST_MODE:-false}"
126+
if [[ "$test_mode" == "true" ]]; then
127+
true
128+
elif [[ "$_specified_version" =~ ^v[0-9]+\.[0-9]+\.[0-9]+ ]]; then
129+
if [[ -z "$_binary_version" ]] || [[ "$_binary_version" != "$_specified_version" ]]; then
130+
_url=${_repo}/releases/download/${_specified_version}/${executable}_${_arch}
131+
_binary_version="${_specified_version}"
132+
fi
133+
else
134+
_latest_version=$(get_latest_version)
135+
if [[ -z "$_latest_version" ]]; then
136+
say "Error: Could not determine latest version"
137+
exit 1
138+
fi
139+
if [[ -z "$_binary_version" ]] || [[ "$_binary_version" != "$_latest_version" ]]; then
140+
_url=${_repo}/releases/download/${_latest_version}/${executable}_${_arch}
141+
_binary_version="${_latest_version}"
142+
fi
143+
fi
99144

100-
if [[ "$test_mode" == "false" ]]; then
101-
if ! downloader "$_url" "$_executable"; then
145+
if [ -n "${_url}" ]; then
146+
if ! downloader "$_url" "${executable}"; then
102147
say "failed to download $_url"
103148
exit 1
104149
fi
150+
echo "${_binary_version}" > "${executable_version_file}"
105151
fi
106152

107153
# todo: move it to a more secure place
108-
chmod +x ${_executable}
154+
chmod +x "${executable}"
109155

110-
./${_executable}
156+
./"${executable}"
111157
}
112158

113159
run_preinstalled_binary() {

pipeline.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"os"
66
"reflect"
7+
"strconv"
78
"strings"
89

910
"github.com/bmatcuk/doublestar/v4"
@@ -104,7 +105,25 @@ func diff(command string) ([]string, error) {
104105
return nil, fmt.Errorf("diff command failed: %v", err)
105106
}
106107

107-
return strings.Fields(strings.TrimSpace(output)), nil
108+
fields := strings.Fields(strings.TrimSpace(output))
109+
paths := make([]string, 0, len(fields))
110+
111+
for _, field := range fields {
112+
// Git quotes paths with special characters using C-style quoting
113+
if strings.HasPrefix(field, "\"") && strings.HasSuffix(field, "\"") {
114+
// Unquote to decode escape sequences (e.g., \360\237\252\201 -> 🪁)
115+
if unquoted, err := strconv.Unquote(field); err == nil {
116+
paths = append(paths, unquoted)
117+
} else {
118+
// If unquoting fails, fall back to removing quotes
119+
paths = append(paths, strings.Trim(field, "\""))
120+
}
121+
} else {
122+
paths = append(paths, field)
123+
}
124+
}
125+
126+
return paths, nil
108127
}
109128

110129
func stepsToTrigger(files []string, watch []WatchConfig) ([]Step, error) {

pipeline_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,34 @@ func TestDiffWithSubshell(t *testing.T) {
119119
assert.Equal(t, want, got)
120120
}
121121

122+
func TestDiffWithQuotedPaths(t *testing.T) {
123+
want := []string{
124+
"projects/test/pages/17_🪁_testfile.py",
125+
"normal/file.txt",
126+
}
127+
got, err := diff(`printf '"projects/test/pages/17_\360\237\252\201_testfile.py" normal/file.txt'`)
128+
assert.NoError(t, err)
129+
assert.Equal(t, want, got)
130+
}
131+
132+
func TestStepsToTriggerWithEmojiPaths(t *testing.T) {
133+
watch := []WatchConfig{
134+
{
135+
Paths: []string{"projects/**"},
136+
Step: Step{Trigger: "test-pipeline"},
137+
},
138+
}
139+
140+
changedFiles := []string{
141+
"projects/test/pages/17_🪁_testfile.py",
142+
"other/file.txt",
143+
}
144+
145+
steps, err := stepsToTrigger(changedFiles, watch)
146+
assert.NoError(t, err)
147+
assert.Equal(t, []Step{{Trigger: "test-pipeline"}}, steps)
148+
}
149+
122150
func TestPipelinesToTriggerGetsListOfPipelines(t *testing.T) {
123151
want := []string{"service-1", "service-2", "service-4"}
124152

0 commit comments

Comments
 (0)