Skip to content

Commit f97fe58

Browse files
committed
Add release manifest helper
1 parent e2ba410 commit f97fe58

2 files changed

Lines changed: 152 additions & 0 deletions

File tree

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Small maintainer wrapper for flattened release preparation.
2+
# It writes the minimal `.dvc` sidecar format directly in pure CMake and does
3+
# not require a local `dvc` installation.
4+
# Reference format:
5+
# https://dvc.org/doc/user-guide/project-structure/dvc-files
6+
7+
if(NOT DEFINED SOURCE_ROOT OR "${SOURCE_ROOT}" STREQUAL "")
8+
message(FATAL_ERROR "NablaAssetManifestsPrepareRelease: SOURCE_ROOT is required")
9+
endif()
10+
if(NOT DEFINED PAYLOAD_ROOT OR "${PAYLOAD_ROOT}" STREQUAL "")
11+
message(FATAL_ERROR "NablaAssetManifestsPrepareRelease: PAYLOAD_ROOT is required")
12+
endif()
13+
if(NOT DEFINED MANIFEST_ROOT OR "${MANIFEST_ROOT}" STREQUAL "")
14+
message(FATAL_ERROR "NablaAssetManifestsPrepareRelease: MANIFEST_ROOT is required")
15+
endif()
16+
if(NOT DEFINED CHANNEL OR "${CHANNEL}" STREQUAL "")
17+
message(FATAL_ERROR "NablaAssetManifestsPrepareRelease: CHANNEL is required")
18+
endif()
19+
20+
get_filename_component(SOURCE_ROOT "${SOURCE_ROOT}" ABSOLUTE)
21+
get_filename_component(PAYLOAD_ROOT "${PAYLOAD_ROOT}" ABSOLUTE)
22+
get_filename_component(MANIFEST_ROOT "${MANIFEST_ROOT}" ABSOLUTE)
23+
set(_channel_manifest_root "${MANIFEST_ROOT}/${CHANNEL}")
24+
25+
if(NOT EXISTS "${SOURCE_ROOT}")
26+
message(FATAL_ERROR "NablaAssetManifestsPrepareRelease: SOURCE_ROOT does not exist: ${SOURCE_ROOT}")
27+
endif()
28+
29+
include("${CMAKE_CURRENT_LIST_DIR}/NablaAssetManifests.cmake")
30+
31+
function(_nam_write_minimal_dvc_manifest OUTPUT_PATH FILE_NAME FILE_MD5 FILE_SIZE)
32+
get_filename_component(_output_dir "${OUTPUT_PATH}" DIRECTORY)
33+
file(MAKE_DIRECTORY "${_output_dir}")
34+
file(WRITE "${OUTPUT_PATH}"
35+
"outs:
36+
- md5: ${FILE_MD5}
37+
size: ${FILE_SIZE}
38+
hash: md5
39+
path: ${FILE_NAME}
40+
")
41+
endfunction()
42+
43+
file(MAKE_DIRECTORY "${PAYLOAD_ROOT}" "${_channel_manifest_root}")
44+
45+
file(GLOB_RECURSE _source_entries RELATIVE "${SOURCE_ROOT}" LIST_DIRECTORIES false "${SOURCE_ROOT}/*")
46+
list(SORT _source_entries)
47+
48+
set(_expected_payloads)
49+
set(_expected_manifests)
50+
51+
foreach(_relative_path IN LISTS _source_entries)
52+
set(_source_path "${SOURCE_ROOT}/${_relative_path}")
53+
if(IS_DIRECTORY "${_source_path}")
54+
continue()
55+
endif()
56+
57+
nam_get_flat_release_asset_name(_flat_asset_name "${_relative_path}")
58+
set(_payload_path "${PAYLOAD_ROOT}/${_flat_asset_name}")
59+
file(COPY_FILE "${_source_path}" "${_payload_path}" ONLY_IF_DIFFERENT)
60+
61+
set(_output_manifest "${_channel_manifest_root}/${_relative_path}.dvc")
62+
file(MD5 "${_source_path}" _file_md5)
63+
file(SIZE "${_source_path}" _file_size)
64+
get_filename_component(_file_name "${_source_path}" NAME)
65+
_nam_write_minimal_dvc_manifest("${_output_manifest}" "${_file_name}" "${_file_md5}" "${_file_size}")
66+
67+
list(APPEND _expected_payloads "${_payload_path}")
68+
list(APPEND _expected_manifests "${_output_manifest}")
69+
endforeach()
70+
71+
if(PRUNE)
72+
file(GLOB _existing_payloads LIST_DIRECTORIES false "${PAYLOAD_ROOT}/*")
73+
foreach(_existing_payload IN LISTS _existing_payloads)
74+
list(FIND _expected_payloads "${_existing_payload}" _payload_index)
75+
if(_payload_index EQUAL -1)
76+
file(REMOVE "${_existing_payload}")
77+
endif()
78+
endforeach()
79+
80+
file(GLOB_RECURSE _existing_manifests LIST_DIRECTORIES false "${_channel_manifest_root}/*.dvc")
81+
foreach(_existing_manifest IN LISTS _existing_manifests)
82+
list(FIND _expected_manifests "${_existing_manifest}" _manifest_index)
83+
if(_manifest_index EQUAL -1)
84+
file(REMOVE "${_existing_manifest}")
85+
endif()
86+
endforeach()
87+
endif()
88+
89+
if(DEFINED MANIFESTS_ZIP AND NOT "${MANIFESTS_ZIP}" STREQUAL "")
90+
get_filename_component(_manifests_zip_dir "${MANIFESTS_ZIP}" DIRECTORY)
91+
file(MAKE_DIRECTORY "${_manifests_zip_dir}")
92+
if(EXISTS "${MANIFESTS_ZIP}")
93+
file(REMOVE "${MANIFESTS_ZIP}")
94+
endif()
95+
execute_process(
96+
COMMAND "${CMAKE_COMMAND}" -E tar cf "${MANIFESTS_ZIP}" --format=zip "${CHANNEL}"
97+
WORKING_DIRECTORY "${MANIFEST_ROOT}"
98+
RESULT_VARIABLE _zip_status
99+
OUTPUT_VARIABLE _zip_stdout
100+
ERROR_VARIABLE _zip_stderr
101+
)
102+
if(NOT _zip_status EQUAL 0)
103+
message(FATAL_ERROR "NablaAssetManifestsPrepareRelease: manifest zip creation failed\n${_zip_stdout}\n${_zip_stderr}")
104+
endif()
105+
endif()
106+
107+
list(LENGTH _expected_payloads _payload_count)
108+
message(STATUS "NablaAssetManifestsPrepareRelease: prepared ${_payload_count} files for channel `${CHANNEL}`")

cmake/README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ The public entrypoint is:
1818
- `nam_materialize_channel_now(...)`
1919
- `nam_get_flat_release_asset_name(...)`
2020

21+
Maintainer-only helper scripts live alongside the consumer module but they are
22+
not part of that public API surface.
23+
2124
### Minimal usage
2225

2326
```cmake
@@ -353,3 +356,44 @@ In a manifest registry repository the maintainer-facing flow is only:
353356
2. run `dvc add` on the changed standalone file or bundle directory
354357
3. commit the updated `.dvc` metadata to Git
355358
4. publish the matching payloads to the backend release channel
359+
360+
### Maintainer helper for flattened releases
361+
362+
The repository also ships a small script-mode helper:
363+
364+
- `cmake/NablaAssetManifestsPrepareRelease.cmake`
365+
366+
It is intended for maintainers who publish flattened release assets but still
367+
want normal `.dvc` files that describe the original package layout.
368+
369+
The helper:
370+
371+
- has no dependency beyond `cmake`
372+
- writes minimal `.dvc` files directly from the source tree
373+
- copies the generated `.dvc` files into a channel tree
374+
- copies payload files into a flattened release payload directory
375+
- optionally prunes stale outputs
376+
- optionally writes a convenience `manifests.zip`
377+
378+
Minimal example:
379+
380+
```cmake
381+
cmake -D SOURCE_ROOT=/abs/package-root ^
382+
-D PAYLOAD_ROOT=/abs/release-payload ^
383+
-D MANIFEST_ROOT=/abs/manifests ^
384+
-D CHANNEL=nsc-windows-x64-release ^
385+
-D MANIFESTS_ZIP=/abs/nsc-windows-x64-release-manifests.zip ^
386+
-D PRUNE=ON ^
387+
-P cmake/NablaAssetManifestsPrepareRelease.cmake
388+
```
389+
390+
Default update mode is incremental:
391+
392+
- existing unchanged manifests stay untouched
393+
- changed files overwrite their matching `.dvc`
394+
- `PRUNE=ON` additionally removes stale payloads and stale `.dvc` files
395+
396+
This helper is for release preparation only. Consumers still use:
397+
398+
- `nam_add_channel_target(...)`
399+
- `nam_materialize_channel_now(...)`

0 commit comments

Comments
 (0)