Skip to content

Commit de08b19

Browse files
committed
feat(in): export all git metadata to files for pipeline access
Write metadata.json and individual files for commit, author, author_date, committer_date, tags, and url. Maintains existing files. Enables access to git metadata during task execution. Signed-off-by: Mathias Bogaert <[email protected]>
1 parent a53ebaa commit de08b19

File tree

3 files changed

+189
-17
lines changed

3 files changed

+189
-17
lines changed

README.md

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -478,27 +478,43 @@ the case.
478478

479479
#### Additional files populated
480480

481-
* `.git/committer`: For committer notification on failed builds.
482-
This special file `.git/committer` which is populated with the email address
483-
of the author of the last commit. This can be used together with an email
484-
resource like [mdomke/concourse-email-resource](https://github.com/mdomke/concourse-email-resource)
485-
to notify the committer in an on_failure step.
481+
* `.git/ref`: Version reference detected and checked out. It will usually contain the commit SHA-1 ref, but also the
482+
detected tag name when using `tag_filter` or `tag_regex`.
486483

487-
* `.git/ref`: Version reference detected and checked out. It will usually contain
488-
the commit SHA-1 ref, but also the detected tag name when using `tag_filter` or
489-
`tag_regex`.
484+
* `.git/commit`: Full SHA-1 commit hash.
485+
486+
* `.git/short_ref`: Short (first seven characters) of the `.git/ref`. Can be templated with `short_ref_format`
487+
parameter.
490488

491489
* `.git/branch`: Name of the original branch that was cloned.
492490

493-
* `.git/short_ref`: Short (first seven characters) of the `.git/ref`. Can be templated with `short_ref_format` parameter.
491+
* `.git/tags`: Comma-separated list of tags associated with this commit.
492+
493+
* `.git/author`: Commit author name.
494+
495+
* `.git/author_date`: Timestamp when the author originally created the commit.
496+
497+
* `.git/committer`: For committer notification on failed builds. This special file `.git/committer` which is populated
498+
with the email address of the author of the last commit. This can be used together with an email resource
499+
like [mdomke/concourse-email-resource](https://github.com/mdomke/concourse-email-resource) to notify the committer in
500+
an on_failure step.
501+
502+
* `.git/committer_name`: Name of the commit author.
503+
504+
* `.git/committer_date`: Timestamp when the commit was added to the repository.
494505

495506
* `.git/commit_message`: For publishing the Git commit message on successful builds.
496507

497508
* `.git/commit_timestamp`: For tagging builds with a timestamp.
498509

499-
* `.git/describe_ref`: Version reference detected and checked out. Can be templated with `describe_ref_options` parameter.
500-
By default, it will contain the `<latest annoted git tag>-<the number of commit since the tag>-g<short_ref>` (eg. `v1.6.2-1-g13dfd7b`).
501-
If the repo was never tagged before, this falls back to a short commit SHA-1 ref.
510+
* `.git/describe_ref`: Version reference detected and checked out. Can be templated with `describe_ref_options`
511+
parameter. By default, it will contain the
512+
`<latest annoted git tag>-<the number of commit since the tag>-g<short_ref>` (eg. `v1.6.2-1-g13dfd7b`). If the repo
513+
was never tagged before, this falls back to a short commit SHA-1 ref.
514+
515+
* `.git/url`: Web URL to view the commit (if applicable).
516+
517+
* `.git/metadata.json`: Complete metadata object in JSON format containing all metadata fields.
502518

503519
### `out`: Push to a repository
504520

assets/in

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,16 +254,32 @@ git --no-pager log -1 --pretty=format:"%an" > .git/committer_name
254254
echo "${return_ref}" > .git/ref
255255

256256
metadata=$(git_metadata)
257-
258-
# Store original cloned branch in .git/branch
259-
echo "${metadata}" | jq -r '.[] | select(.name == "branch") | .value' > .git/branch
257+
echo "${metadata}" | jq '.' > .git/metadata.json
260258

261259
# Store short ref with templating. Useful to build Docker images with
262260
# a custom tag
263261
echo "${return_ref}" | cut -c1-7 | awk "{ printf \"${short_ref_format}\", \$1 }" > .git/short_ref
264262

263+
# Write individual metadata fields to separate files
264+
265+
# .git/commit - full SHA hash
266+
echo "${metadata}" | jq -r '.[] | select(.name == "commit") | .value' > .git/commit
267+
# .git/author - commit author name
268+
echo "${metadata}" | jq -r '.[] | select(.name == "author") | .value' > .git/author
269+
# .git/author_date - timestamp when the author originally created the commit
270+
echo "${metadata}" | jq -r '.[] | select(.name == "author_date") | .value' > .git/author_date
271+
272+
# .git/tags - branch name(s) containing this commit (comma-separated if multiple)
273+
echo "${metadata}" | jq -r '.[] | select(.name == "branch") | .value // ""' > .git/branch
274+
# .git/tags - comma-separated list of tags
275+
echo "${metadata}" | jq -r '.[] | select(.name == "tags") | .value // ""' > .git/tags
276+
# .git/url - web URL to view commit (if applicable)
277+
echo "${metadata}" | jq -r '.[] | select(.name == "url") | .value // ""' > .git/url
278+
# .git/committer_date - timestamp when the commit was created in the repository
279+
echo "${metadata}" | jq -r '.[] | select(.name == "committer_date") | .value // ""' > .git/committer_date
280+
265281
# Store commit message in .git/commit_message. Can be used to inform about
266-
# the content of a successfull build.
282+
# the content of a successful build.
267283
# Using https://github.com/cloudfoundry-community/slack-notification-resource
268284
# for example
269285
git log -1 --format=format:%B > .git/commit_message

test/get.sh

Lines changed: 141 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ it_omits_empty_branch_in_metadata() {
124124
"
125125
}
126126

127-
128127
it_returns_branch_in_metadata() {
129128
local repo=$(init_repo)
130129
local ref1=$(make_commit_to_branch $repo branch-a)
@@ -176,6 +175,146 @@ it_returns_list_of_tags_in_metadata() {
176175
"
177176
}
178177

178+
it_writes_complete_metadata_files() {
179+
local repo=$(init_repo)
180+
181+
# Create a commit with specific author/committer info
182+
git -C $repo \
183+
-c user.name='alice' \
184+
-c user.email='[email protected]' \
185+
commit --allow-empty -m "test commit message"
186+
local ref=$(git -C $repo rev-parse HEAD)
187+
188+
# Add multiple tags to test tag aggregation
189+
git -C $repo tag v1.0.0
190+
git -C $repo tag v1.0.0-rc1
191+
git -C $repo tag latest
192+
193+
local dest=$TMPDIR/destination
194+
get_uri $repo $dest | jq -e "
195+
.version == {ref: $(echo $ref | jq -R .)}
196+
"
197+
198+
# === Verify metadata.json ===
199+
test -e $dest/.git/metadata.json || \
200+
( echo ".git/metadata.json does not exist"; return 1 )
201+
202+
cat $dest/.git/metadata.json | jq -e '. | length > 0' > /dev/null || \
203+
( echo ".git/metadata.json is not valid JSON or is empty"; return 1 )
204+
205+
# === Verify all metadata files ===
206+
207+
# .git/commit
208+
test -e $dest/.git/commit || \
209+
( echo ".git/commit does not exist"; return 1 )
210+
test "$(cat $dest/.git/commit)" = "$ref" || \
211+
( echo ".git/commit content mismatch"; return 1 )
212+
213+
# .git/author
214+
test -e $dest/.git/author || \
215+
( echo ".git/author does not exist"; return 1 )
216+
test "$(cat $dest/.git/author)" = "alice" || \
217+
( echo ".git/author content mismatch"; return 1 )
218+
219+
# .git/author_date
220+
test -e $dest/.git/author_date || \
221+
( echo ".git/author_date does not exist"; return 1 )
222+
echo "$(cat $dest/.git/author_date)" | grep -qE "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} [+-][0-9]{4}$" || \
223+
( echo ".git/author_date format invalid: $(cat $dest/.git/author_date)"; return 1 )
224+
225+
# .git/committer
226+
test -e $dest/.git/committer || \
227+
( echo ".git/committer does not exist"; return 1 )
228+
test "$(cat $dest/.git/committer)" = "[email protected]" || \
229+
( echo ".git/committer content mismatch"; return 1 )
230+
231+
# .git/committer_name
232+
test -e $dest/.git/committer_name || \
233+
( echo ".git/committer_name does not exist"; return 1 )
234+
test "$(cat $dest/.git/committer_name)" = "alice" || \
235+
( echo ".git/committer_name content mismatch"; return 1 )
236+
237+
# .git/committer_date
238+
test -e $dest/.git/committer_date || \
239+
( echo ".git/committer_date does not exist"; return 1 )
240+
echo "$(cat $dest/.git/committer_date)" | grep -qE "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} [+-][0-9]{4}$" || \
241+
( echo ".git/committer_date format invalid"; return 1 )
242+
243+
# .git/ref
244+
test -e $dest/.git/ref || \
245+
( echo ".git/ref does not exist"; return 1 )
246+
test "$(cat $dest/.git/ref)" = "$ref" || \
247+
( echo ".git/ref content mismatch"; return 1 )
248+
249+
# .git/branch
250+
test -e $dest/.git/branch || \
251+
( echo ".git/branch does not exist"; return 1 )
252+
test "$(cat $dest/.git/branch)" = "master" || \
253+
( echo ".git/branch content mismatch"; return 1 )
254+
255+
# .git/short_ref
256+
test -e $dest/.git/short_ref || \
257+
( echo ".git/short_ref does not exist"; return 1 )
258+
local expected_short="test-$(echo $ref | cut -c1-7)"
259+
test "$(cat $dest/.git/short_ref)" = "$expected_short" || \
260+
( echo ".git/short_ref content mismatch"; return 1 )
261+
262+
# .git/commit_message
263+
test -e $dest/.git/commit_message || \
264+
( echo ".git/commit_message does not exist"; return 1 )
265+
grep -q "test commit message" $dest/.git/commit_message || \
266+
( echo ".git/commit_message content mismatch"; return 1 )
267+
268+
# .git/commit_timestamp
269+
test -e $dest/.git/commit_timestamp || \
270+
( echo ".git/commit_timestamp does not exist"; return 1 )
271+
test -n "$(cat $dest/.git/commit_timestamp)" || \
272+
( echo ".git/commit_timestamp is empty"; return 1 )
273+
274+
# .git/describe_ref
275+
test -e $dest/.git/describe_ref || \
276+
( echo ".git/describe_ref does not exist"; return 1 )
277+
278+
# .git/tags
279+
test -e $dest/.git/tags || \
280+
( echo ".git/tags does not exist"; return 1 )
281+
local tags=$(cat $dest/.git/tags)
282+
test -n "$tags" || \
283+
( echo ".git/tags is empty when tags exist"; return 1 )
284+
echo "$tags" | grep -q "v1.0.0" || \
285+
( echo ".git/tags missing v1.0.0"; return 1 )
286+
echo "$tags" | grep -q "v1.0.0-rc1" || \
287+
( echo ".git/tags missing v1.0.0-rc1"; return 1 )
288+
echo "$tags" | grep -q "latest" || \
289+
( echo ".git/tags missing latest"; return 1 )
290+
291+
# .git/url
292+
test -e $dest/.git/url || \
293+
( echo ".git/url does not exist"; return 1 )
294+
test -z "$(cat $dest/.git/url)" || \
295+
( echo ".git/url should be empty for local repo"; return 1 )
296+
297+
# === Test edge case: no tags ===
298+
rm -rf $dest
299+
local repo_notags=$(init_repo)
300+
local ref_notags=$(make_commit $repo_notags)
301+
get_uri $repo_notags $dest
302+
303+
test -e $dest/.git/tags || \
304+
( echo ".git/tags does not exist when no tags present"; return 1 )
305+
test -z "$(cat $dest/.git/tags)" || \
306+
( echo ".git/tags should be empty when no tags exist"; return 1 )
307+
308+
# === Verify metadata.json structure ===
309+
local has_commit=$(cat $dest/.git/metadata.json | jq '[.[] | select(.name == "commit")] | length')
310+
test "$has_commit" = "1" || \
311+
( echo "metadata.json missing commit field"; return 1 )
312+
313+
local has_author=$(cat $dest/.git/metadata.json | jq '[.[] | select(.name == "author")] | length')
314+
test "$has_author" = "1" || \
315+
( echo "metadata.json missing author field"; return 1 )
316+
}
317+
179318
it_can_use_submodules_without_perl_warning() {
180319
local repo=$(init_repo_with_submodule | cut -d "," -f1)
181320
local dest=$TMPDIR/destination
@@ -951,6 +1090,7 @@ run it_omits_empty_branch_in_metadata
9511090
run it_returns_branch_in_metadata
9521091
run it_omits_empty_tags_in_metadata
9531092
run it_returns_list_of_tags_in_metadata
1093+
run it_writes_complete_metadata_files
9541094
run it_honors_the_depth_flag
9551095
run it_can_get_from_url_at_depth_at_ref
9561096
run it_falls_back_to_deep_clone_if_ref_not_found

0 commit comments

Comments
 (0)