diff --git a/MODULE.bazel b/MODULE.bazel index 311e5c0bb6a0813e60715497e5d1765991cedc49..31e307f2918fefda550b96b7422359f9d8c6e6b0 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -5,6 +5,7 @@ module( ], ) +bazel_dep(name = "bazel_skylib", version = "1.5.0") bazel_dep(name = "toolchain_utils", version = "1.0.0-beta.9") bazel_dep(name = "ape", version = "1.0.0-beta.6") diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 197277a83cc00e3648619319b4b96b3583728b37..6fbba1d8a025d2d0dd551043ce542ccc1baa12a4 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -15,6 +15,7 @@ "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651", + "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138", "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/source.json": "082ed5f9837901fada8c68c2f3ddc958bb22b6d654f71dd73f3df30d45d4b749", "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", diff --git a/curl/upload/BUILD.bazel b/curl/upload/BUILD.bazel new file mode 100644 index 0000000000000000000000000000000000000000..284cdfa58c660cc4a8178b930f45a04f01ed2386 --- /dev/null +++ b/curl/upload/BUILD.bazel @@ -0,0 +1,16 @@ +exports_files([ + "posix.tmpl.sh", + "nt.tmpl.bat", +]) + +alias( + name = "template", + actual = select( + { + "@toolchain_utils//toolchain/constraint/os:windows": ":nt.tmpl.bat", + "//conditions:default": ":posix.tmpl.sh", + }, + no_match_error = "No script template available for `curl_upload_file`", + ), + visibility = ["//visibility:public"], +) diff --git a/curl/upload/ManifestInfo.bzl b/curl/upload/ManifestInfo.bzl new file mode 100644 index 0000000000000000000000000000000000000000..17edaa6700d4893e08fc5203a9da3d4adc21a050 --- /dev/null +++ b/curl/upload/ManifestInfo.bzl @@ -0,0 +1,50 @@ +load("@bazel_skylib//lib:types.bzl", "types") + +visibility("public") + +def init(file, url = "{href}/{dst}/{basename}"): + """ + Initializes a `CurlUploadManifestInfo` provider. + + To be used with `curl_upload_manifests` + + Args: + file: The file to upload. + url: A Starlark string template for the URL, which can include: + - href: the provided + - dst: the directory to upload into + - path: the full path of the source file + - dirname: the directory name of the source file + - basename: the basename of the source file + - stem: the stem of the source file + - extension: the extension of the source file + Defaults to `{href}/{dst}/{basename}` + + Returns: + A mapping of keywords for the `curl_upload_manifest_info` raw constructor. + """ + if type(file) != "File": + fail("`CurlUploadManifestInfo.file` must be a `file`: {}".format(file)) + + if file.is_directory: + fail("`CurlUploadManifestInfo.file` must not be a directory: {}".format(file)) + + if not types.is_string(url): + fail("`CurlUploadManifestInfo.url` must be a `str`: {}".format(url)) + + return { + "file": file, + "url": url, + } + +CurlUploadManifestInfo, curl_upload_manifest_info = provider( + "A file to upload with cURL.", + fields = ["file", "url"], + init = init, +) + +# Provide some convenience imports +ManifestInfo = CurlUploadManifestInfo +manifest_info = curl_upload_manifest_info +Info = CurlUploadManifestInfo +info = curl_upload_manifest_info diff --git a/curl/upload/ManifestsInfo.bzl b/curl/upload/ManifestsInfo.bzl new file mode 100644 index 0000000000000000000000000000000000000000..9bf15e75275b82617030ce1767c1aba17890b598 --- /dev/null +++ b/curl/upload/ManifestsInfo.bzl @@ -0,0 +1,34 @@ +load("@bazel_skylib//lib:types.bzl", "types") + +visibility("public") + +def init(manifests): + """ + Initializes a `CurlUploadManifestsInfo` provider. + + To be used with `curl_upload_manifests` + + Args: + manifests: The dependency set of `CurlUploadManifestInfo`s + + Returns: + A mapping of keywords for the `curl_upload_manifests_info` raw constructor. + """ + if not types.is_depset(manifests): + fail("`CurlUploadManifestsInfo.url` must be a `depset`: {}".format(manifests)) + + return { + "manifests": manifests, + } + +CurlUploadManifestsInfo, curl_upload_manifests_info = provider( + "Files to upload with cURL.", + fields = ["manifests"], + init = init, +) + +# Provide some convenience imports +ManifestsInfo = CurlUploadManifestsInfo +manifests_info = curl_upload_manifests_info +Info = CurlUploadManifestsInfo +info = curl_upload_manifests_info diff --git a/curl/upload/file/BUILD.bazel b/curl/upload/file/BUILD.bazel index 284cdfa58c660cc4a8178b930f45a04f01ed2386..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/curl/upload/file/BUILD.bazel +++ b/curl/upload/file/BUILD.bazel @@ -1,16 +0,0 @@ -exports_files([ - "posix.tmpl.sh", - "nt.tmpl.bat", -]) - -alias( - name = "template", - actual = select( - { - "@toolchain_utils//toolchain/constraint/os:windows": ":nt.tmpl.bat", - "//conditions:default": ":posix.tmpl.sh", - }, - no_match_error = "No script template available for `curl_upload_file`", - ), - visibility = ["//visibility:public"], -) diff --git a/curl/upload/file/rule.bzl b/curl/upload/file/rule.bzl index 01e149c68128d5a53105b7368c9e167c5007d27d..c571123390e03a52d165ddac0b99db85a706a048 100644 --- a/curl/upload/file/rule.bzl +++ b/curl/upload/file/rule.bzl @@ -36,7 +36,7 @@ ATTRS = { ), "template": attr.label( doc = "The template that is expanded into the upload binary.", - default = ":template", + default = "//curl/upload:template", allow_single_file = True, ), } @@ -53,6 +53,7 @@ def implementation(ctx): substitutions.add("{{retry_delay}}", str(ctx.attr.retry_delay)) substitutions.add("{{src}}", str(ctx.file.src.short_path)) substitutions.add("{{dst}}", str(ctx.attr.dst)) + substitutions.add("{{input_data}}", "") # must be empty ctx.actions.expand_template( template = ctx.file.template, diff --git a/curl/upload/files/BUILD.bazel b/curl/upload/files/BUILD.bazel new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/curl/upload/files/defs.bzl b/curl/upload/files/defs.bzl new file mode 100644 index 0000000000000000000000000000000000000000..6463a798cec1217cb776f733c40a548e7137f0dd --- /dev/null +++ b/curl/upload/files/defs.bzl @@ -0,0 +1,5 @@ +load(":rule.bzl", _files = "files") + +visibility("public") + +curl_upload_files = _files diff --git a/curl/upload/files/rule.bzl b/curl/upload/files/rule.bzl new file mode 100644 index 0000000000000000000000000000000000000000..eb0f9c9b63ff80308c7fe0b31b49c4774d925c22 --- /dev/null +++ b/curl/upload/files/rule.bzl @@ -0,0 +1,116 @@ +load("//curl/upload:ManifestInfo.bzl", "ManifestInfo") +load("//curl/upload:ManifestsInfo.bzl", "ManifestsInfo") + +visibility("//curl/...") + +DOC = """Upload bunch of files to a URL endpoint with cURL. + +The `srcs` must provide `ManifestInfo` or `ManifestsInfo`. + +```py +file( + name = "upload_files", + srcs = [ + ":data", + ], + dst = "path/to/prefix" + url = "https://host.name.to.upload", +) +``` +""" + +ATTRS = { + "srcs": attr.label_list( + doc = "Files to be uploaded.", + mandatory = True, + providers = [ + [ManifestInfo], + [ManifestsInfo], + ], + ), + "dst": attr.string( + doc = "The destination directory to upload.", + default = "", + ), + "url": attr.string( + doc = "URL endpoint for files to upload.", + mandatory = True, + ), + "retry": attr.int( + doc = "The number of retry attempts for every file.", + default = 3, + ), + "retry_delay": attr.int( + doc = "The seconds to wait before attempting an upload retry.", + default = 1, + ), + "template": attr.label( + doc = "The template that is expanded into the upload binary.", + default = "//curl/upload:template", + allow_single_file = True, + ), +} + +def implementation(ctx): + curl = ctx.toolchains["//curl/toolchain/curl:type"] + + upload_data = ctx.actions.declare_file("upload.csv") + manifests = depset( + direct = [src[ManifestInfo] for src in ctx.attr.srcs if ManifestInfo in src], + transitive = [src[ManifestsInfo].manifests for src in ctx.attr.srcs if ManifestsInfo in src], + ) + + href = ctx.attr.url.rstrip("/") + dst = ctx.attr.dst.rstrip("/") + + def _to_string(m): + _url = m.url.format( + path = m.file.path, + dirname = m.file.dirname, + basename = m.file.basename, + extension = m.file.extension, + href = href, + dst = dst, + stem = m.file.basename.rstrip(".{}".format(m.file.extension)), + ) + return "{},{}".format(m.file.short_path, _url) + + args = ctx.actions.args() + args.add_all(manifests, map_each = _to_string, allow_closure = True) + ctx.actions.write(upload_data, args, is_executable = False) + + executable = ctx.actions.declare_file("{}.sh".format(ctx.label.name)) + + substitutions = ctx.actions.template_dict() + substitutions.add("{{curl}}", str(curl.executable.short_path)) + substitutions.add("{{url}}", ctx.attr.url.rstrip("/")) + substitutions.add("{{retry}}", str(ctx.attr.retry)) + substitutions.add("{{retry_delay}}", str(ctx.attr.retry_delay)) + substitutions.add("{{src}}", "") + substitutions.add("{{dst}}", str(ctx.attr.dst)) + substitutions.add("{{upload_data}}", str(upload_data.short_path)) + + ctx.actions.expand_template( + template = ctx.file.template, + output = executable, + computed_substitutions = substitutions, + is_executable = True, + ) + + files = depset([executable]) + runfiles = ctx.runfiles([curl.executable, upload_data] + ctx.files.srcs + [m.file for m in manifests.to_list()]) + runfiles = runfiles.merge(curl.default.default_runfiles) + + return DefaultInfo( + executable = executable, + files = files, + runfiles = runfiles, + ) + +files = rule( + doc = DOC, + attrs = ATTRS, + implementation = implementation, + toolchains = ["//curl/toolchain/curl:type"], + executable = True, +) diff --git a/curl/upload/file/nt.tmpl.bat b/curl/upload/nt.tmpl.bat similarity index 100% rename from curl/upload/file/nt.tmpl.bat rename to curl/upload/nt.tmpl.bat diff --git a/curl/upload/file/posix.tmpl.sh b/curl/upload/posix.tmpl.sh similarity index 71% rename from curl/upload/file/posix.tmpl.sh rename to curl/upload/posix.tmpl.sh index 59ee3425a50f4c72d0209564b80868afc5613283..6e0d43e567075598263ab4aff15ea00bde2c08fb 100644 --- a/curl/upload/file/posix.tmpl.sh +++ b/curl/upload/posix.tmpl.sh @@ -8,9 +8,10 @@ CURL="{{curl}}" SRC="{{src}}" DST="{{dst}}" URL="{{url}}" +UPLOAD_DATA="{{upload_data}}" RETRY="{{retry}}" RETRY_DELAY="{{retry_delay}}" -readonly CURL SRC DST URL RETRY RETRY_DELAY +readonly CURL SRC DST URL RETRY RETRY_DELAY UPLOAD_DATA # Runfiles RUNFILES_DIR="${RUNFILES_DIR-${0}.runfiles}" @@ -62,14 +63,25 @@ readonly ENDPOINT DIRECTORY DESTINATION COMPOSED="${ENDPOINT}${DIRECTORY}${DESTINATION}" readonly COMPOSED -printf >&2 "Uploading: %s to %s\n" "${SRC}" "${COMPOSED}" +upload() { -# Do the upload -"${RUNFILES}/${CURL}" \ - --netrc \ - --location \ - --progress-bar \ - --retry "${RETRY}" \ - --retry-delay "${RETRY_DELAY}" \ - --upload-file "${RUNFILES}/${SRC}" \ - "${COMPOSED}" + printf >&2 "Uploading: %s to %s\n" "${1}" "${2}" + + # Do the upload + "${RUNFILES}/${CURL}" \ + --netrc \ + --location \ + --progress-bar \ + --retry "${RETRY}" \ + --retry-delay "${RETRY_DELAY}" \ + --upload-file "${RUNFILES}/${1}" \ + "${2}" +} + +if test -n ${UPLOAD_DATA} && test -f "${RUNFILES}/${UPLOAD_DATA}"; then + while IFS= read -r line; do + upload "${line%,*}" "${line#*,}" + done <"${RUNFILES}/${UPLOAD_DATA}" +else + upload "${SRC}" "${COMPOSED}" +fi diff --git a/e2e/MODULE.bazel b/e2e/MODULE.bazel index 03a276eea53dd1eac24a751997ad03553dc28d9d..cec2f492fa23fb3e23f9d1957f3bd3bb6b848834 100644 --- a/e2e/MODULE.bazel +++ b/e2e/MODULE.bazel @@ -7,6 +7,7 @@ module( bazel_dep(name = "bazel_skylib", version = "1.5.0") bazel_dep(name = "toolchain_utils", version = "1.0.0-beta.9") +bazel_dep(name = "rules_diff", version = "1.0.0-beta.3") bazel_dep(name = "rules_curl") local_path_override( module_name = "rules_curl", diff --git a/e2e/MODULE.bazel.lock b/e2e/MODULE.bazel.lock index fca858b2905059dab0cb05c222f3687515bc3517..933c582c15d1e92e0b3190e108278fec5179a011 100644 --- a/e2e/MODULE.bazel.lock +++ b/e2e/MODULE.bazel.lock @@ -39,6 +39,8 @@ "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", "https://bcr.bazel.build/modules/rules_cc/0.0.9/source.json": "1f1ba6fea244b616de4a554a0f4983c91a9301640c8fe0dd1d410254115c8430", + "https://bcr.bazel.build/modules/rules_diff/1.0.0-beta.3/MODULE.bazel": "4bcae1c5e3c7fa1169f9940f548f7b8b3316944b4367771b168f925b7a9ee74e", + "https://bcr.bazel.build/modules/rules_diff/1.0.0-beta.3/source.json": "b5db3fcd469061f2051188da97345162f294fc59e7fdf477beb306dbe950566a", "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", "https://bcr.bazel.build/modules/rules_java/7.6.1/source.json": "8f3f3076554e1558e8e468b2232991c510ecbcbed9e6f8c06ac31c93bcf38362", @@ -117,7 +119,7 @@ "@@toolchain_utils~//toolchain/export:defs.bzl%toolchain_export": { "general": { "bzlTransitiveDigest": "n2fd+/jiAv/nvvi2WUR+VQxI3aTZGNuhuX/NuFhw5fM=", - "usagesDigest": "A2BbbNuBP0QFNqjCVowoaEOrolUDkTAis6lyamxEXLE=", + "usagesDigest": "OT9pdXtWdZUfYUSpReUZ6+fci56uJ5AVYR22QqnoBYI=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, @@ -374,6 +376,13 @@ "target": "@@ape~~_repo_rules~seq//:seq" } }, + "diff": { + "bzlFile": "@@toolchain_utils~//toolchain/export/symlink:repository.bzl", + "ruleClassName": "symlink", + "attributes": { + "target": "@@toolchain_utils~~toolchain_export~ape-diff//:ape-diff" + } + }, "ape-printenv": { "bzlFile": "@@toolchain_utils~//toolchain/export/symlink:repository.bzl", "ruleClassName": "symlink", @@ -549,6 +558,13 @@ "target": "@@ape~~_repo_rules~qjs//:qjs" } }, + "cmp": { + "bzlFile": "@@toolchain_utils~//toolchain/export/symlink:repository.bzl", + "ruleClassName": "symlink", + "attributes": { + "target": "@@toolchain_utils~~toolchain_export~ape-cmp//:ape-cmp" + } + }, "ape-df": { "bzlFile": "@@toolchain_utils~//toolchain/export/symlink:repository.bzl", "ruleClassName": "symlink", @@ -738,6 +754,20 @@ "target": "@@ape~~_repo_rules~nohup//:nohup" } }, + "sdiff": { + "bzlFile": "@@toolchain_utils~//toolchain/export/symlink:repository.bzl", + "ruleClassName": "symlink", + "attributes": { + "target": "@@toolchain_utils~~toolchain_export~ape-sdiff//:ape-sdiff" + } + }, + "diff3": { + "bzlFile": "@@toolchain_utils~//toolchain/export/symlink:repository.bzl", + "ruleClassName": "symlink", + "attributes": { + "target": "@@toolchain_utils~~toolchain_export~ape-diff3//:ape-diff3" + } + }, "ape-basename": { "bzlFile": "@@toolchain_utils~//toolchain/export/symlink:repository.bzl", "ruleClassName": "symlink", diff --git a/e2e/mock/manifest/BUILD.bazel b/e2e/mock/manifest/BUILD.bazel new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/e2e/mock/manifest/rule.bzl b/e2e/mock/manifest/rule.bzl new file mode 100644 index 0000000000000000000000000000000000000000..79e997eb31265e1bbdcea85e974d7a43c4ba5783 --- /dev/null +++ b/e2e/mock/manifest/rule.bzl @@ -0,0 +1,33 @@ +load("@rules_curl//curl/upload:ManifestInfo.bzl", "ManifestInfo") + +DOC = """Mock rule with output `ManifestInfo` provider. + +```py +mock_manifest( + name = "mock_file", +) +``` +""" + +def _impl(ctx): + out = ctx.actions.declare_file("{}.out".format(ctx.attr.name)) + + ctx.actions.write(out, "hello test", is_executable = False) + + return [ + DefaultInfo( + files = depset([out]), + ), + ManifestInfo( + file = out, + url = "{href}/{basename}", + ), + ] + +mock_manifest = rule( + doc = DOC, + implementation = _impl, + provides = [ + ManifestInfo, + ], +) diff --git a/e2e/mock/manifests/BUILD.bazel b/e2e/mock/manifests/BUILD.bazel new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/e2e/mock/manifests/rule.bzl b/e2e/mock/manifests/rule.bzl new file mode 100644 index 0000000000000000000000000000000000000000..e422988ae917761236bc7a46a37702057dec69d1 --- /dev/null +++ b/e2e/mock/manifests/rule.bzl @@ -0,0 +1,57 @@ +load("@rules_curl//curl/upload:ManifestInfo.bzl", "ManifestInfo", "manifest_info") +load("@rules_curl//curl/upload:ManifestsInfo.bzl", "ManifestsInfo") + +DOC = """Mock rule with output `ManifestsInfo` provider. + +```py +mock_manifests( + name = "mock_files", + outs = [ + "file_1.out", + "file_2.out", + ], + deps = [ + "my_dep", + ], +) +``` +""" + +ATTRS = { + "outs": attr.string_list( + default = [], + mandatory = True, + ), + "deps": attr.label_list(allow_files = True), +} + +def _impl(ctx): + outs = [ctx.actions.declare_file(o) for o in ctx.attr.outs] + + for f in outs: + ctx.actions.write(f, "hello test", is_executable = False) + + files = depset(outs) + + manifests = [manifest_info(file = o, url = "{href}/{dst}/{stem}.{extension}") for o in outs] + manifests.extend([dep[ManifestInfo] for dep in ctx.attr.deps if ManifestInfo in dep]) + + transitive = [dep[ManifestsInfo].manifests for dep in ctx.attr.deps if ManifestsInfo in dep] + + return [ + DefaultInfo( + files = files, + ), + ManifestsInfo( + manifests = depset(direct = manifests, transitive = transitive), + ), + ] + +mock_manifests = rule( + doc = DOC, + attrs = ATTRS, + implementation = _impl, + provides = [ + ManifestsInfo, + ], +) diff --git a/e2e/upload/file/BUILD.bazel b/e2e/upload/file/BUILD.bazel index 625955743c5554ab69d5ab43d827b5331219bc67..6826b0828727363027b0de7698639489904e2acc 100644 --- a/e2e/upload/file/BUILD.bazel +++ b/e2e/upload/file/BUILD.bazel @@ -1,5 +1,5 @@ -load("@bazel_skylib//rules:diff_test.bzl", "diff_test") load("@rules_curl//curl/upload/file:defs.bzl", "curl_upload_file") +load("@rules_diff//diff/file/test:defs.bzl", "diff_file_test") curl_upload_file( name = "upload", @@ -19,8 +19,9 @@ genrule( tools = [":upload"], ) -diff_test( +diff_file_test( name = "test", - file1 = ":fixture.txt", - file2 = ":execute", + size = "small", + a = ":fixture.txt", + b = ":execute", ) diff --git a/e2e/upload/files/BUILD.bazel b/e2e/upload/files/BUILD.bazel new file mode 100644 index 0000000000000000000000000000000000000000..cf6521418ae948757dcb552626854dca16a28e34 --- /dev/null +++ b/e2e/upload/files/BUILD.bazel @@ -0,0 +1,72 @@ +load("@rules_curl//curl/upload/files:defs.bzl", "curl_upload_files") +load("@rules_diff//diff/file/test:defs.bzl", "diff_file_test") +load("//mock/manifest:rule.bzl", "mock_manifest") +load("//mock/manifests:rule.bzl", "mock_manifests") + +genrule( + name = "data", + testonly = True, + outs = [ + "data.out", + ], + cmd = "echo 'Hello data\n' > $@", +) + +mock_manifest( + name = "fixture_1", +) + +mock_manifest( + name = "fixture_2", +) + +mock_manifests( + name = "file_pack_1", + testonly = True, + outs = [ + "file_1.out", + "file_2.out", + ], +) + +mock_manifests( + name = "file_pack_2", + testonly = True, + outs = [ + "file_A.txt", + "file_B.txt", + ], + deps = [ + ":data", + ":file_pack_1", + ":fixture_2", + ], +) + +curl_upload_files( + name = "upload_files", + testonly = True, + srcs = [ + ":file_pack_2", + ":fixture_1", + ], + dst = "destination/directory/to/upload", + url = "https://test.case", +) + +genrule( + name = "execute", + testonly = True, + outs = [ + "upload_files.out", + ], + cmd = "./$(location :upload_files) > $@", + tools = [":upload_files"], +) + +diff_file_test( + name = "test", + size = "small", + a = ":fixture.txt", + b = ":execute", +) diff --git a/e2e/upload/files/fixture.txt b/e2e/upload/files/fixture.txt new file mode 100644 index 0000000000000000000000000000000000000000..f6e85f59365f4192dd8bd7caf74494964597ccaf --- /dev/null +++ b/e2e/upload/files/fixture.txt @@ -0,0 +1,60 @@ +--netrc +--location +--progress-bar +--retry +3 +--retry-delay +1 +--upload-file +file_1.out +https://test.case/destination/directory/to/upload/file_1.out +--netrc +--location +--progress-bar +--retry +3 +--retry-delay +1 +--upload-file +file_2.out +https://test.case/destination/directory/to/upload/file_2.out +--netrc +--location +--progress-bar +--retry +3 +--retry-delay +1 +--upload-file +file_A.txt +https://test.case/destination/directory/to/upload/file_A.txt +--netrc +--location +--progress-bar +--retry +3 +--retry-delay +1 +--upload-file +file_B.txt +https://test.case/destination/directory/to/upload/file_B.txt +--netrc +--location +--progress-bar +--retry +3 +--retry-delay +1 +--upload-file +fixture_2.out +https://test.case/fixture_2.out +--netrc +--location +--progress-bar +--retry +3 +--retry-delay +1 +--upload-file +fixture_1.out +https://test.case/fixture_1.out