Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,6 +86,7 @@ When you run `bazel run ///helloworld:mynamespace.apply`, it applies this file i
| ***release_branch_prefix*** | `master` | A git branch name/prefix. Automatically run GitOps while building this branch. See [GitOps and Deployment](#gitops_and_deployment).
| ***deployment_branch*** | `None` | Automatic GitOps output will appear in a branch and PR with this name. See [GitOps and Deployment](#gitops_and_deployment).
| ***gitops_path*** | `cloud` | Path within the git repo where gitops files get generated into
| ***app_grp*** | `` | Optional folder for grouping apps after gitops_path in git repo
| ***tags*** | `[]` | See [Bazel docs on tags](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).
| ***visibility*** | [Default_visibility](https://docs.bazel.build/versions/master/be/functions.html#package.default_visibility) | Changes the visibility of all rules generated by this macro. See [Bazel docs on visibility](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).

Expand Down
4 changes: 4 additions & 0 deletions examples/e2e-test.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,7 @@ rm -rf cloud
bazel run //helloworld:canary.gitops
bazel run //helloworld:release.gitops
bazel run //helloworld:gitops_custom_path.gitops
bazel run //helloworld:gitops_with_app_grp.gitops
#the result of .gitops operation goes into /cloud directory and should be submitted back to the repo

#apply everything generated
Expand All@@ -48,5 +49,8 @@ kubectl apply -f cloud -R
#apply gitops_custom_path gen
kubectl apply -f custom_cloud -R

#apply gitops_with_app_grp gen (should create cloud/backend/hwteam/kind-kind/ structure)
kubectl apply -f cloud/backend -R

#wait for readiness
kubectl -n hwteam wait --timeout=60s --for=condition=Available deployment/helloworld deployment/helloworld-canary deployment/helloworld-gitops-custom-path
20 changes: 20 additions & 0 deletions examples/helloworld/BUILD
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,6 +123,26 @@ k8s_deploy(
user = USER,
)

k8s_deploy(
name = "gitops_with_app_grp",
app_grp = "backend", # This will create path: cloud/backend/hwteam/kind-kind/gitops_with_app_grp.yaml
cluster = CLUSTER,
deployment_branch = "helloworld-gitops-app-grp",
# image_digest_tag = True, # test optional image tagging
# image_registry = REGISTRY, # override the default registry host for production
# image_repository_prefix = "k8s",
images = {
"helloworld-image": ":image",
},
manifests = [
"deployment.yaml",
"service.yaml",
],
name_suffix = "-gitops-app-grp",
namespace = NAMESPACE,
user = USER,
)

sh_test(
name = "k8s_deploy_test",
srcs = ["k8s_deploy_test.sh"],
Expand Down
2 changes: 2 additions & 0 deletions skylib/k8s.bzl
Original file line numberDiff line numberDiff line change
Expand Up@@ -111,6 +111,7 @@ def k8s_deploy(
cluster = "dev",
user = "{BUILD_USER}",
namespace = None,
app_grp = None, # optional application group to insert between gitops_path and namespace in the file path
configmaps_srcs = None,
secrets_srcs = None,
configmaps_renaming = None, # configmaps renaming policy. Could be None or 'hash'.
Expand DownExpand Up@@ -279,6 +280,7 @@ def k8s_deploy(
srcs = [name],
cluster = cluster,
namespace = namespace,
app_grp = app_grp,
gitops_path = gitops_path,
strip_prefixes = [
namespace + "-",
Expand Down
20 changes: 16 additions & 4 deletions skylib/kustomize/kustomize.bzl
Original file line numberDiff line numberDiff line change
Expand Up@@ -440,19 +440,30 @@ fi
""".format(push_statements)

namespace = ctx.attr.namespace
app_grp = ctx.attr.app_grp

# Construct the path with optional app_grp
if app_grp:
path_template = "{gitops_path}/{app_grp}/{namespace}/{cluster}/{file}"
mkdir_template = "{gitops_path}/{app_grp}/{namespace}/{cluster}"
else:
path_template = "{gitops_path}/{namespace}/{cluster}/{file}"
mkdir_template = "{gitops_path}/{namespace}/{cluster}"

for inattr in ctx.attr.srcs:
if "{" in namespace:
fail("unable to gitops namespace with placeholders %s" % inattr.label) #mynamespace should not be gitopsed
for infile in inattr.files.to_list():
statements += ("echo $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n" +
"mkdir -p $TARGET_DIR/{gitops_path}/{namespace}/{cluster}\n" +
"echo '# GENERATED BY {rulename} -> {gitopsrulename}' > $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n" +
"{template_engine} --template={infile} --variable=NAMESPACE={namespace} --stamp_info_file={info_file} >> $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n").format(
statements += ("echo $TARGET_DIR/" + path_template + "\n" +
"mkdir -p $TARGET_DIR/" + mkdir_template + "\n" +
"echo '# GENERATED BY {rulename} -> {gitopsrulename}' > $TARGET_DIR/" + path_template + "\n" +
"{template_engine} --template={infile} --variable=NAMESPACE={namespace} --stamp_info_file={info_file} >> $TARGET_DIR/" + path_template + "\n").format(
infile = infile.path,
rulename = inattr.label,
gitopsrulename = ctx.label,
namespace = namespace,
gitops_path = ctx.attr.gitops_path,
app_grp = app_grp,
cluster = cluster,
file = _remove_prefixes(infile.path.split("/")[-1], strip_prefixes),
template_engine = "${RUNFILES}/%s" % _get_runfile_path(ctx, ctx.executable._template_engine),
Expand DownExpand Up@@ -485,6 +496,7 @@ gitops = rule(
"srcs": attr.label_list(providers = (KustomizeInfo,)),
"cluster": attr.string(mandatory = True),
"namespace": attr.string(mandatory = True),
"app_grp": attr.string(doc = "optional application group to insert between gitops_path and namespace in the file path"),
"deployment_branch": attr.string(),
"gitops_path": attr.string(),
"release_branch_prefix": attr.string(),
Expand Down
51 changes: 51 additions & 0 deletions skylib/kustomize/tests/BUILD
Original file line numberDiff line numberDiff line change
Expand Up@@ -270,6 +270,57 @@ gitops(
namespace = "test",
)

# Test gitops with app_grp parameter
gitops(
name = "dev-something-with-app-grp.gitops",
testonly = True,
srcs = [":namespace_test"],
app_grp = "backend",
cluster = "dev",
gitops_path = "cloud",
namespace = "test",
)

# Test gitops without app_grp (should behave like original)
gitops(
name = "dev-something-no-app-grp.gitops",
testonly = True,
srcs = [":namespace_test"],
cluster = "dev",
gitops_path = "cloud",
namespace = "test",
# app_grp intentionally omitted to test backward compatibility
)

# Test rules to verify gitops output with app_grp
rule_test(
name = "gitops_with_app_grp_generates_executable",
generates = ["dev-something-with-app-grp.gitops"],
rule = "dev-something-with-app-grp.gitops",
)

# Test rules to verify gitops output without app_grp (backward compatibility)
rule_test(
name = "gitops_no_app_grp_generates_executable",
generates = ["dev-something-no-app-grp.gitops"],
rule = "dev-something-no-app-grp.gitops",
)

# File tests to verify gitops path generation
file_test(
name = "gitops_with_app_grp_path_test",
file = ":dev-something-with-app-grp.gitops",
matches = 4, # Should appear in echo, mkdir, echo comment, and template_engine commands
regexp = "cloud/backend",
)

file_test(
name = "gitops_no_app_grp_path_test",
file = ":dev-something-no-app-grp.gitops",
matches = 4, # Should appear in echo, mkdir, echo comment, and template_engine commands
regexp = "cloud/test/dev",
)

#-------------------
kustomize(
name = "name_prefix",
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,6 +86,7 @@ When you run `bazel run ///helloworld:mynamespace.apply`, it applies this file i
| ***release_branch_prefix*** | `master` | A git branch name/prefix. Automatically run GitOps while building this branch. See [GitOps and Deployment](#gitops_and_deployment).
| ***deployment_branch*** | `None` | Automatic GitOps output will appear in a branch and PR with this name. See [GitOps and Deployment](#gitops_and_deployment).
| ***gitops_path*** | `cloud` | Path within the git repo where gitops files get generated into
| ***app_grp*** | `` | Optional folder for grouping apps after gitops_path in git repo
| ***tags*** | `[]` | See [Bazel docs on tags](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).
| ***visibility*** | [Default_visibility](https://docs.bazel.build/versions/master/be/functions.html#package.default_visibility) | Changes the visibility of all rules generated by this macro. See [Bazel docs on visibility](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).

Expand Down
4 changes: 4 additions & 0 deletions examples/e2e-test.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,7 @@ rm -rf cloud
bazel run //helloworld:canary.gitops
bazel run //helloworld:release.gitops
bazel run //helloworld:gitops_custom_path.gitops
bazel run //helloworld:gitops_with_app_grp.gitops
#the result of .gitops operation goes into /cloud directory and should be submitted back to the repo

#apply everything generated
Expand All@@ -48,5 +49,8 @@ kubectl apply -f cloud -R
#apply gitops_custom_path gen
kubectl apply -f custom_cloud -R

#apply gitops_with_app_grp gen (should create cloud/backend/hwteam/kind-kind/ structure)
kubectl apply -f cloud/backend -R

#wait for readiness
kubectl -n hwteam wait --timeout=60s --for=condition=Available deployment/helloworld deployment/helloworld-canary deployment/helloworld-gitops-custom-path
20 changes: 20 additions & 0 deletions examples/helloworld/BUILD
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,6 +123,26 @@ k8s_deploy(
user = USER,
)

k8s_deploy(
name = "gitops_with_app_grp",
app_grp = "backend", # This will create path: cloud/backend/hwteam/kind-kind/gitops_with_app_grp.yaml
cluster = CLUSTER,
deployment_branch = "helloworld-gitops-app-grp",
# image_digest_tag = True, # test optional image tagging
# image_registry = REGISTRY, # override the default registry host for production
# image_repository_prefix = "k8s",
images = {
"helloworld-image": ":image",
},
manifests = [
"deployment.yaml",
"service.yaml",
],
name_suffix = "-gitops-app-grp",
namespace = NAMESPACE,
user = USER,
)

sh_test(
name = "k8s_deploy_test",
srcs = ["k8s_deploy_test.sh"],
Expand Down
2 changes: 2 additions & 0 deletions skylib/k8s.bzl
Original file line numberDiff line numberDiff line change
Expand Up@@ -111,6 +111,7 @@ def k8s_deploy(
cluster = "dev",
user = "{BUILD_USER}",
namespace = None,
app_grp = None, # optional application group to insert between gitops_path and namespace in the file path
configmaps_srcs = None,
secrets_srcs = None,
configmaps_renaming = None, # configmaps renaming policy. Could be None or 'hash'.
Expand DownExpand Up@@ -279,6 +280,7 @@ def k8s_deploy(
srcs = [name],
cluster = cluster,
namespace = namespace,
app_grp = app_grp,
gitops_path = gitops_path,
strip_prefixes = [
namespace + "-",
Expand Down
20 changes: 16 additions & 4 deletions skylib/kustomize/kustomize.bzl
Original file line numberDiff line numberDiff line change
Expand Up@@ -440,19 +440,30 @@ fi
""".format(push_statements)

namespace = ctx.attr.namespace
app_grp = ctx.attr.app_grp

# Construct the path with optional app_grp
if app_grp:
path_template = "{gitops_path}/{app_grp}/{namespace}/{cluster}/{file}"
mkdir_template = "{gitops_path}/{app_grp}/{namespace}/{cluster}"
else:
path_template = "{gitops_path}/{namespace}/{cluster}/{file}"
mkdir_template = "{gitops_path}/{namespace}/{cluster}"

for inattr in ctx.attr.srcs:
if "{" in namespace:
fail("unable to gitops namespace with placeholders %s" % inattr.label) #mynamespace should not be gitopsed
for infile in inattr.files.to_list():
statements += ("echo $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n" +
"mkdir -p $TARGET_DIR/{gitops_path}/{namespace}/{cluster}\n" +
"echo '# GENERATED BY {rulename} -> {gitopsrulename}' > $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n" +
"{template_engine} --template={infile} --variable=NAMESPACE={namespace} --stamp_info_file={info_file} >> $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n").format(
statements += ("echo $TARGET_DIR/" + path_template + "\n" +
"mkdir -p $TARGET_DIR/" + mkdir_template + "\n" +
"echo '# GENERATED BY {rulename} -> {gitopsrulename}' > $TARGET_DIR/" + path_template + "\n" +
"{template_engine} --template={infile} --variable=NAMESPACE={namespace} --stamp_info_file={info_file} >> $TARGET_DIR/" + path_template + "\n").format(
infile = infile.path,
rulename = inattr.label,
gitopsrulename = ctx.label,
namespace = namespace,
gitops_path = ctx.attr.gitops_path,
app_grp = app_grp,
cluster = cluster,
file = _remove_prefixes(infile.path.split("/")[-1], strip_prefixes),
template_engine = "${RUNFILES}/%s" % _get_runfile_path(ctx, ctx.executable._template_engine),
Expand DownExpand Up@@ -485,6 +496,7 @@ gitops = rule(
"srcs": attr.label_list(providers = (KustomizeInfo,)),
"cluster": attr.string(mandatory = True),
"namespace": attr.string(mandatory = True),
"app_grp": attr.string(doc = "optional application group to insert between gitops_path and namespace in the file path"),
"deployment_branch": attr.string(),
"gitops_path": attr.string(),
"release_branch_prefix": attr.string(),
Expand Down
51 changes: 51 additions & 0 deletions skylib/kustomize/tests/BUILD
Original file line numberDiff line numberDiff line change
Expand Up@@ -270,6 +270,57 @@ gitops(
namespace = "test",
)

# Test gitops with app_grp parameter
gitops(
name = "dev-something-with-app-grp.gitops",
testonly = True,
srcs = [":namespace_test"],
app_grp = "backend",
cluster = "dev",
gitops_path = "cloud",
namespace = "test",
)

# Test gitops without app_grp (should behave like original)
gitops(
name = "dev-something-no-app-grp.gitops",
testonly = True,
srcs = [":namespace_test"],
cluster = "dev",
gitops_path = "cloud",
namespace = "test",
# app_grp intentionally omitted to test backward compatibility
)

# Test rules to verify gitops output with app_grp
rule_test(
name = "gitops_with_app_grp_generates_executable",
generates = ["dev-something-with-app-grp.gitops"],
rule = "dev-something-with-app-grp.gitops",
)

# Test rules to verify gitops output without app_grp (backward compatibility)
rule_test(
name = "gitops_no_app_grp_generates_executable",
generates = ["dev-something-no-app-grp.gitops"],
rule = "dev-something-no-app-grp.gitops",
)

# File tests to verify gitops path generation
file_test(
name = "gitops_with_app_grp_path_test",
file = ":dev-something-with-app-grp.gitops",
matches = 4, # Should appear in echo, mkdir, echo comment, and template_engine commands
regexp = "cloud/backend",
)

file_test(
name = "gitops_no_app_grp_path_test",
file = ":dev-something-no-app-grp.gitops",
matches = 4, # Should appear in echo, mkdir, echo comment, and template_engine commands
regexp = "cloud/test/dev",
)

#-------------------
kustomize(
name = "name_prefix",
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,6 +86,7 @@ When you run `bazel run ///helloworld:mynamespace.apply`, it applies this file i
| ***release_branch_prefix*** | `master` | A git branch name/prefix. Automatically run GitOps while building this branch. See [GitOps and Deployment](#gitops_and_deployment).
| ***deployment_branch*** | `None` | Automatic GitOps output will appear in a branch and PR with this name. See [GitOps and Deployment](#gitops_and_deployment).
| ***gitops_path*** | `cloud` | Path within the git repo where gitops files get generated into
| ***app_grp*** | `` | Optional folder for grouping apps after gitops_path in git repo
| ***tags*** | `[]` | See [Bazel docs on tags](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).
| ***visibility*** | [Default_visibility](https://docs.bazel.build/versions/master/be/functions.html#package.default_visibility) | Changes the visibility of all rules generated by this macro. See [Bazel docs on visibility](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).

Expand Down
4 changes: 4 additions & 0 deletions examples/e2e-test.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,7 @@ rm -rf cloud
bazel run //helloworld:canary.gitops
bazel run //helloworld:release.gitops
bazel run //helloworld:gitops_custom_path.gitops
bazel run //helloworld:gitops_with_app_grp.gitops
#the result of .gitops operation goes into /cloud directory and should be submitted back to the repo

#apply everything generated
Expand All@@ -48,5 +49,8 @@ kubectl apply -f cloud -R
#apply gitops_custom_path gen
kubectl apply -f custom_cloud -R

#apply gitops_with_app_grp gen (should create cloud/backend/hwteam/kind-kind/ structure)
kubectl apply -f cloud/backend -R

#wait for readiness
kubectl -n hwteam wait --timeout=60s --for=condition=Available deployment/helloworld deployment/helloworld-canary deployment/helloworld-gitops-custom-path
20 changes: 20 additions & 0 deletions examples/helloworld/BUILD
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,6 +123,26 @@ k8s_deploy(
user = USER,
)

k8s_deploy(
name = "gitops_with_app_grp",
app_grp = "backend", # This will create path: cloud/backend/hwteam/kind-kind/gitops_with_app_grp.yaml
cluster = CLUSTER,
deployment_branch = "helloworld-gitops-app-grp",
# image_digest_tag = True, # test optional image tagging
# image_registry = REGISTRY, # override the default registry host for production
# image_repository_prefix = "k8s",
images = {
"helloworld-image": ":image",
},
manifests = [
"deployment.yaml",
"service.yaml",
],
name_suffix = "-gitops-app-grp",
namespace = NAMESPACE,
user = USER,
)

sh_test(
name = "k8s_deploy_test",
srcs = ["k8s_deploy_test.sh"],
Expand Down
2 changes: 2 additions & 0 deletions skylib/k8s.bzl
Original file line numberDiff line numberDiff line change
Expand Up@@ -111,6 +111,7 @@ def k8s_deploy(
cluster = "dev",
user = "{BUILD_USER}",
namespace = None,
app_grp = None, # optional application group to insert between gitops_path and namespace in the file path
configmaps_srcs = None,
secrets_srcs = None,
configmaps_renaming = None, # configmaps renaming policy. Could be None or 'hash'.
Expand DownExpand Up@@ -279,6 +280,7 @@ def k8s_deploy(
srcs = [name],
cluster = cluster,
namespace = namespace,
app_grp = app_grp,
gitops_path = gitops_path,
strip_prefixes = [
namespace + "-",
Expand Down
20 changes: 16 additions & 4 deletions skylib/kustomize/kustomize.bzl
Original file line numberDiff line numberDiff line change
Expand Up@@ -440,19 +440,30 @@ fi
""".format(push_statements)

namespace = ctx.attr.namespace
app_grp = ctx.attr.app_grp

# Construct the path with optional app_grp
if app_grp:
path_template = "{gitops_path}/{app_grp}/{namespace}/{cluster}/{file}"
mkdir_template = "{gitops_path}/{app_grp}/{namespace}/{cluster}"
else:
path_template = "{gitops_path}/{namespace}/{cluster}/{file}"
mkdir_template = "{gitops_path}/{namespace}/{cluster}"

for inattr in ctx.attr.srcs:
if "{" in namespace:
fail("unable to gitops namespace with placeholders %s" % inattr.label) #mynamespace should not be gitopsed
for infile in inattr.files.to_list():
statements += ("echo $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n" +
"mkdir -p $TARGET_DIR/{gitops_path}/{namespace}/{cluster}\n" +
"echo '# GENERATED BY {rulename} -> {gitopsrulename}' > $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n" +
"{template_engine} --template={infile} --variable=NAMESPACE={namespace} --stamp_info_file={info_file} >> $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n").format(
statements += ("echo $TARGET_DIR/" + path_template + "\n" +
"mkdir -p $TARGET_DIR/" + mkdir_template + "\n" +
"echo '# GENERATED BY {rulename} -> {gitopsrulename}' > $TARGET_DIR/" + path_template + "\n" +
"{template_engine} --template={infile} --variable=NAMESPACE={namespace} --stamp_info_file={info_file} >> $TARGET_DIR/" + path_template + "\n").format(
infile = infile.path,
rulename = inattr.label,
gitopsrulename = ctx.label,
namespace = namespace,
gitops_path = ctx.attr.gitops_path,
app_grp = app_grp,
cluster = cluster,
file = _remove_prefixes(infile.path.split("/")[-1], strip_prefixes),
template_engine = "${RUNFILES}/%s" % _get_runfile_path(ctx, ctx.executable._template_engine),
Expand DownExpand Up@@ -485,6 +496,7 @@ gitops = rule(
"srcs": attr.label_list(providers = (KustomizeInfo,)),
"cluster": attr.string(mandatory = True),
"namespace": attr.string(mandatory = True),
"app_grp": attr.string(doc = "optional application group to insert between gitops_path and namespace in the file path"),
"deployment_branch": attr.string(),
"gitops_path": attr.string(),
"release_branch_prefix": attr.string(),
Expand Down
51 changes: 51 additions & 0 deletions skylib/kustomize/tests/BUILD
Original file line numberDiff line numberDiff line change
Expand Up@@ -270,6 +270,57 @@ gitops(
namespace = "test",
)

# Test gitops with app_grp parameter
gitops(
name = "dev-something-with-app-grp.gitops",
testonly = True,
srcs = [":namespace_test"],
app_grp = "backend",
cluster = "dev",
gitops_path = "cloud",
namespace = "test",
)

# Test gitops without app_grp (should behave like original)
gitops(
name = "dev-something-no-app-grp.gitops",
testonly = True,
srcs = [":namespace_test"],
cluster = "dev",
gitops_path = "cloud",
namespace = "test",
# app_grp intentionally omitted to test backward compatibility
)

# Test rules to verify gitops output with app_grp
rule_test(
name = "gitops_with_app_grp_generates_executable",
generates = ["dev-something-with-app-grp.gitops"],
rule = "dev-something-with-app-grp.gitops",
)

# Test rules to verify gitops output without app_grp (backward compatibility)
rule_test(
name = "gitops_no_app_grp_generates_executable",
generates = ["dev-something-no-app-grp.gitops"],
rule = "dev-something-no-app-grp.gitops",
)

# File tests to verify gitops path generation
file_test(
name = "gitops_with_app_grp_path_test",
file = ":dev-something-with-app-grp.gitops",
matches = 4, # Should appear in echo, mkdir, echo comment, and template_engine commands
regexp = "cloud/backend",
)

file_test(
name = "gitops_no_app_grp_path_test",
file = ":dev-something-no-app-grp.gitops",
matches = 4, # Should appear in echo, mkdir, echo comment, and template_engine commands
regexp = "cloud/test/dev",
)

#-------------------
kustomize(
name = "name_prefix",
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,6 +86,7 @@ When you run `bazel run ///helloworld:mynamespace.apply`, it applies this file i
| ***release_branch_prefix*** | `master` | A git branch name/prefix. Automatically run GitOps while building this branch. See [GitOps and Deployment](#gitops_and_deployment).
| ***deployment_branch*** | `None` | Automatic GitOps output will appear in a branch and PR with this name. See [GitOps and Deployment](#gitops_and_deployment).
| ***gitops_path*** | `cloud` | Path within the git repo where gitops files get generated into
| ***app_grp*** | `` | Optional folder for grouping apps after gitops_path in git repo
| ***tags*** | `[]` | See [Bazel docs on tags](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).
| ***visibility*** | [Default_visibility](https://docs.bazel.build/versions/master/be/functions.html#package.default_visibility) | Changes the visibility of all rules generated by this macro. See [Bazel docs on visibility](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).

Expand Down
4 changes: 4 additions & 0 deletions examples/e2e-test.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,7 @@ rm -rf cloud
bazel run //helloworld:canary.gitops
bazel run //helloworld:release.gitops
bazel run //helloworld:gitops_custom_path.gitops
bazel run //helloworld:gitops_with_app_grp.gitops
#the result of .gitops operation goes into /cloud directory and should be submitted back to the repo

#apply everything generated
Expand All@@ -48,5 +49,8 @@ kubectl apply -f cloud -R
#apply gitops_custom_path gen
kubectl apply -f custom_cloud -R

#apply gitops_with_app_grp gen (should create cloud/backend/hwteam/kind-kind/ structure)
kubectl apply -f cloud/backend -R

#wait for readiness
kubectl -n hwteam wait --timeout=60s --for=condition=Available deployment/helloworld deployment/helloworld-canary deployment/helloworld-gitops-custom-path
20 changes: 20 additions & 0 deletions examples/helloworld/BUILD
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,6 +123,26 @@ k8s_deploy(
user = USER,
)

k8s_deploy(
name = "gitops_with_app_grp",
app_grp = "backend", # This will create path: cloud/backend/hwteam/kind-kind/gitops_with_app_grp.yaml
cluster = CLUSTER,
deployment_branch = "helloworld-gitops-app-grp",
# image_digest_tag = True, # test optional image tagging
# image_registry = REGISTRY, # override the default registry host for production
# image_repository_prefix = "k8s",
images = {
"helloworld-image": ":image",
},
manifests = [
"deployment.yaml",
"service.yaml",
],
name_suffix = "-gitops-app-grp",
namespace = NAMESPACE,
user = USER,
)

sh_test(
name = "k8s_deploy_test",
srcs = ["k8s_deploy_test.sh"],
Expand Down
2 changes: 2 additions & 0 deletions skylib/k8s.bzl
Original file line numberDiff line numberDiff line change
Expand Up@@ -111,6 +111,7 @@ def k8s_deploy(
cluster = "dev",
user = "{BUILD_USER}",
namespace = None,
app_grp = None, # optional application group to insert between gitops_path and namespace in the file path
configmaps_srcs = None,
secrets_srcs = None,
configmaps_renaming = None, # configmaps renaming policy. Could be None or 'hash'.
Expand DownExpand Up@@ -279,6 +280,7 @@ def k8s_deploy(
srcs = [name],
cluster = cluster,
namespace = namespace,
app_grp = app_grp,
gitops_path = gitops_path,
strip_prefixes = [
namespace + "-",
Expand Down
20 changes: 16 additions & 4 deletions skylib/kustomize/kustomize.bzl
Original file line numberDiff line numberDiff line change
Expand Up@@ -440,19 +440,30 @@ fi
""".format(push_statements)

namespace = ctx.attr.namespace
app_grp = ctx.attr.app_grp

# Construct the path with optional app_grp
if app_grp:
path_template = "{gitops_path}/{app_grp}/{namespace}/{cluster}/{file}"
mkdir_template = "{gitops_path}/{app_grp}/{namespace}/{cluster}"
else:
path_template = "{gitops_path}/{namespace}/{cluster}/{file}"
mkdir_template = "{gitops_path}/{namespace}/{cluster}"

for inattr in ctx.attr.srcs:
if "{" in namespace:
fail("unable to gitops namespace with placeholders %s" % inattr.label) #mynamespace should not be gitopsed
for infile in inattr.files.to_list():
statements += ("echo $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n" +
"mkdir -p $TARGET_DIR/{gitops_path}/{namespace}/{cluster}\n" +
"echo '# GENERATED BY {rulename} -> {gitopsrulename}' > $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n" +
"{template_engine} --template={infile} --variable=NAMESPACE={namespace} --stamp_info_file={info_file} >> $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n").format(
statements += ("echo $TARGET_DIR/" + path_template + "\n" +
"mkdir -p $TARGET_DIR/" + mkdir_template + "\n" +
"echo '# GENERATED BY {rulename} -> {gitopsrulename}' > $TARGET_DIR/" + path_template + "\n" +
"{template_engine} --template={infile} --variable=NAMESPACE={namespace} --stamp_info_file={info_file} >> $TARGET_DIR/" + path_template + "\n").format(
infile = infile.path,
rulename = inattr.label,
gitopsrulename = ctx.label,
namespace = namespace,
gitops_path = ctx.attr.gitops_path,
app_grp = app_grp,
cluster = cluster,
file = _remove_prefixes(infile.path.split("/")[-1], strip_prefixes),
template_engine = "${RUNFILES}/%s" % _get_runfile_path(ctx, ctx.executable._template_engine),
Expand DownExpand Up@@ -485,6 +496,7 @@ gitops = rule(
"srcs": attr.label_list(providers = (KustomizeInfo,)),
"cluster": attr.string(mandatory = True),
"namespace": attr.string(mandatory = True),
"app_grp": attr.string(doc = "optional application group to insert between gitops_path and namespace in the file path"),
"deployment_branch": attr.string(),
"gitops_path": attr.string(),
"release_branch_prefix": attr.string(),
Expand Down
51 changes: 51 additions & 0 deletions skylib/kustomize/tests/BUILD
Original file line numberDiff line numberDiff line change
Expand Up@@ -270,6 +270,57 @@ gitops(
namespace = "test",
)

# Test gitops with app_grp parameter
gitops(
name = "dev-something-with-app-grp.gitops",
testonly = True,
srcs = [":namespace_test"],
app_grp = "backend",
cluster = "dev",
gitops_path = "cloud",
namespace = "test",
)

# Test gitops without app_grp (should behave like original)
gitops(
name = "dev-something-no-app-grp.gitops",
testonly = True,
srcs = [":namespace_test"],
cluster = "dev",
gitops_path = "cloud",
namespace = "test",
# app_grp intentionally omitted to test backward compatibility
)

# Test rules to verify gitops output with app_grp
rule_test(
name = "gitops_with_app_grp_generates_executable",
generates = ["dev-something-with-app-grp.gitops"],
rule = "dev-something-with-app-grp.gitops",
)

# Test rules to verify gitops output without app_grp (backward compatibility)
rule_test(
name = "gitops_no_app_grp_generates_executable",
generates = ["dev-something-no-app-grp.gitops"],
rule = "dev-something-no-app-grp.gitops",
)

# File tests to verify gitops path generation
file_test(
name = "gitops_with_app_grp_path_test",
file = ":dev-something-with-app-grp.gitops",
matches = 4, # Should appear in echo, mkdir, echo comment, and template_engine commands
regexp = "cloud/backend",
)

file_test(
name = "gitops_no_app_grp_path_test",
file = ":dev-something-no-app-grp.gitops",
matches = 4, # Should appear in echo, mkdir, echo comment, and template_engine commands
regexp = "cloud/test/dev",
)

#-------------------
kustomize(
name = "name_prefix",
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,6 +86,7 @@ When you run `bazel run ///helloworld:mynamespace.apply`, it applies this file i
| ***release_branch_prefix*** | `master` | A git branch name/prefix. Automatically run GitOps while building this branch. See [GitOps and Deployment](#gitops_and_deployment).
| ***deployment_branch*** | `None` | Automatic GitOps output will appear in a branch and PR with this name. See [GitOps and Deployment](#gitops_and_deployment).
| ***gitops_path*** | `cloud` | Path within the git repo where gitops files get generated into
| ***app_grp*** | `` | Optional folder for grouping apps after gitops_path in git repo
| ***tags*** | `[]` | See [Bazel docs on tags](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).
| ***visibility*** | [Default_visibility](https://docs.bazel.build/versions/master/be/functions.html#package.default_visibility) | Changes the visibility of all rules generated by this macro. See [Bazel docs on visibility](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).

Expand Down
4 changes: 4 additions & 0 deletions examples/e2e-test.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,7 @@ rm -rf cloud
bazel run //helloworld:canary.gitops
bazel run //helloworld:release.gitops
bazel run //helloworld:gitops_custom_path.gitops
bazel run //helloworld:gitops_with_app_grp.gitops
#the result of .gitops operation goes into /cloud directory and should be submitted back to the repo

#apply everything generated
Expand All@@ -48,5 +49,8 @@ kubectl apply -f cloud -R
#apply gitops_custom_path gen
kubectl apply -f custom_cloud -R

#apply gitops_with_app_grp gen (should create cloud/backend/hwteam/kind-kind/ structure)
kubectl apply -f cloud/backend -R

#wait for readiness
kubectl -n hwteam wait --timeout=60s --for=condition=Available deployment/helloworld deployment/helloworld-canary deployment/helloworld-gitops-custom-path
20 changes: 20 additions & 0 deletions examples/helloworld/BUILD
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,6 +123,26 @@ k8s_deploy(
user = USER,
)

k8s_deploy(
name = "gitops_with_app_grp",
app_grp = "backend", # This will create path: cloud/backend/hwteam/kind-kind/gitops_with_app_grp.yaml
cluster = CLUSTER,
deployment_branch = "helloworld-gitops-app-grp",
# image_digest_tag = True, # test optional image tagging
# image_registry = REGISTRY, # override the default registry host for production
# image_repository_prefix = "k8s",
images = {
"helloworld-image": ":image",
},
manifests = [
"deployment.yaml",
"service.yaml",
],
name_suffix = "-gitops-app-grp",
namespace = NAMESPACE,
user = USER,
)

sh_test(
name = "k8s_deploy_test",
srcs = ["k8s_deploy_test.sh"],
Expand Down
2 changes: 2 additions & 0 deletions skylib/k8s.bzl
Original file line numberDiff line numberDiff line change
Expand Up@@ -111,6 +111,7 @@ def k8s_deploy(
cluster = "dev",
user = "{BUILD_USER}",
namespace = None,
app_grp = None, # optional application group to insert between gitops_path and namespace in the file path
configmaps_srcs = None,
secrets_srcs = None,
configmaps_renaming = None, # configmaps renaming policy. Could be None or 'hash'.
Expand DownExpand Up@@ -279,6 +280,7 @@ def k8s_deploy(
srcs = [name],
cluster = cluster,
namespace = namespace,
app_grp = app_grp,
gitops_path = gitops_path,
strip_prefixes = [
namespace + "-",
Expand Down
20 changes: 16 additions & 4 deletions skylib/kustomize/kustomize.bzl
Original file line numberDiff line numberDiff line change
Expand Up@@ -440,19 +440,30 @@ fi
""".format(push_statements)

namespace = ctx.attr.namespace
app_grp = ctx.attr.app_grp

# Construct the path with optional app_grp
if app_grp:
path_template = "{gitops_path}/{app_grp}/{namespace}/{cluster}/{file}"
mkdir_template = "{gitops_path}/{app_grp}/{namespace}/{cluster}"
else:
path_template = "{gitops_path}/{namespace}/{cluster}/{file}"
mkdir_template = "{gitops_path}/{namespace}/{cluster}"

for inattr in ctx.attr.srcs:
if "{" in namespace:
fail("unable to gitops namespace with placeholders %s" % inattr.label) #mynamespace should not be gitopsed
for infile in inattr.files.to_list():
statements += ("echo $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n" +
"mkdir -p $TARGET_DIR/{gitops_path}/{namespace}/{cluster}\n" +
"echo '# GENERATED BY {rulename} -> {gitopsrulename}' > $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n" +
"{template_engine} --template={infile} --variable=NAMESPACE={namespace} --stamp_info_file={info_file} >> $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n").format(
statements += ("echo $TARGET_DIR/" + path_template + "\n" +
"mkdir -p $TARGET_DIR/" + mkdir_template + "\n" +
"echo '# GENERATED BY {rulename} -> {gitopsrulename}' > $TARGET_DIR/" + path_template + "\n" +
"{template_engine} --template={infile} --variable=NAMESPACE={namespace} --stamp_info_file={info_file} >> $TARGET_DIR/" + path_template + "\n").format(
infile = infile.path,
rulename = inattr.label,
gitopsrulename = ctx.label,
namespace = namespace,
gitops_path = ctx.attr.gitops_path,
app_grp = app_grp,
cluster = cluster,
file = _remove_prefixes(infile.path.split("/")[-1], strip_prefixes),
template_engine = "${RUNFILES}/%s" % _get_runfile_path(ctx, ctx.executable._template_engine),
Expand DownExpand Up@@ -485,6 +496,7 @@ gitops = rule(
"srcs": attr.label_list(providers = (KustomizeInfo,)),
"cluster": attr.string(mandatory = True),
"namespace": attr.string(mandatory = True),
"app_grp": attr.string(doc = "optional application group to insert between gitops_path and namespace in the file path"),
"deployment_branch": attr.string(),
"gitops_path": attr.string(),
"release_branch_prefix": attr.string(),
Expand Down
51 changes: 51 additions & 0 deletions skylib/kustomize/tests/BUILD
Original file line numberDiff line numberDiff line change
Expand Up@@ -270,6 +270,57 @@ gitops(
namespace = "test",
)

# Test gitops with app_grp parameter
gitops(
name = "dev-something-with-app-grp.gitops",
testonly = True,
srcs = [":namespace_test"],
app_grp = "backend",
cluster = "dev",
gitops_path = "cloud",
namespace = "test",
)

# Test gitops without app_grp (should behave like original)
gitops(
name = "dev-something-no-app-grp.gitops",
testonly = True,
srcs = [":namespace_test"],
cluster = "dev",
gitops_path = "cloud",
namespace = "test",
# app_grp intentionally omitted to test backward compatibility
)

# Test rules to verify gitops output with app_grp
rule_test(
name = "gitops_with_app_grp_generates_executable",
generates = ["dev-something-with-app-grp.gitops"],
rule = "dev-something-with-app-grp.gitops",
)

# Test rules to verify gitops output without app_grp (backward compatibility)
rule_test(
name = "gitops_no_app_grp_generates_executable",
generates = ["dev-something-no-app-grp.gitops"],
rule = "dev-something-no-app-grp.gitops",
)

# File tests to verify gitops path generation
file_test(
name = "gitops_with_app_grp_path_test",
file = ":dev-something-with-app-grp.gitops",
matches = 4, # Should appear in echo, mkdir, echo comment, and template_engine commands
regexp = "cloud/backend",
)

file_test(
name = "gitops_no_app_grp_path_test",
file = ":dev-something-no-app-grp.gitops",
matches = 4, # Should appear in echo, mkdir, echo comment, and template_engine commands
regexp = "cloud/test/dev",
)

#-------------------
kustomize(
name = "name_prefix",
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,6 +86,7 @@ When you run `bazel run ///helloworld:mynamespace.apply`, it applies this file i
| ***release_branch_prefix*** | `master` | A git branch name/prefix. Automatically run GitOps while building this branch. See [GitOps and Deployment](#gitops_and_deployment).
| ***deployment_branch*** | `None` | Automatic GitOps output will appear in a branch and PR with this name. See [GitOps and Deployment](#gitops_and_deployment).
| ***gitops_path*** | `cloud` | Path within the git repo where gitops files get generated into
| ***app_grp*** | `` | Optional folder for grouping apps after gitops_path in git repo
| ***tags*** | `[]` | See [Bazel docs on tags](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).
| ***visibility*** | [Default_visibility](https://docs.bazel.build/versions/master/be/functions.html#package.default_visibility) | Changes the visibility of all rules generated by this macro. See [Bazel docs on visibility](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).

Expand Down
4 changes: 4 additions & 0 deletions examples/e2e-test.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,7 @@ rm -rf cloud
bazel run //helloworld:canary.gitops
bazel run //helloworld:release.gitops
bazel run //helloworld:gitops_custom_path.gitops
bazel run //helloworld:gitops_with_app_grp.gitops
#the result of .gitops operation goes into /cloud directory and should be submitted back to the repo

#apply everything generated
Expand All@@ -48,5 +49,8 @@ kubectl apply -f cloud -R
#apply gitops_custom_path gen
kubectl apply -f custom_cloud -R

#apply gitops_with_app_grp gen (should create cloud/backend/hwteam/kind-kind/ structure)
kubectl apply -f cloud/backend -R

#wait for readiness
kubectl -n hwteam wait --timeout=60s --for=condition=Available deployment/helloworld deployment/helloworld-canary deployment/helloworld-gitops-custom-path
20 changes: 20 additions & 0 deletions examples/helloworld/BUILD
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,6 +123,26 @@ k8s_deploy(
user = USER,
)

k8s_deploy(
name = "gitops_with_app_grp",
app_grp = "backend", # This will create path: cloud/backend/hwteam/kind-kind/gitops_with_app_grp.yaml
cluster = CLUSTER,
deployment_branch = "helloworld-gitops-app-grp",
# image_digest_tag = True, # test optional image tagging
# image_registry = REGISTRY, # override the default registry host for production
# image_repository_prefix = "k8s",
images = {
"helloworld-image": ":image",
},
manifests = [
"deployment.yaml",
"service.yaml",
],
name_suffix = "-gitops-app-grp",
namespace = NAMESPACE,
user = USER,
)

sh_test(
name = "k8s_deploy_test",
srcs = ["k8s_deploy_test.sh"],
Expand Down
2 changes: 2 additions & 0 deletions skylib/k8s.bzl
Original file line numberDiff line numberDiff line change
Expand Up@@ -111,6 +111,7 @@ def k8s_deploy(
cluster = "dev",
user = "{BUILD_USER}",
namespace = None,
app_grp = None, # optional application group to insert between gitops_path and namespace in the file path
configmaps_srcs = None,
secrets_srcs = None,
configmaps_renaming = None, # configmaps renaming policy. Could be None or 'hash'.
Expand DownExpand Up@@ -279,6 +280,7 @@ def k8s_deploy(
srcs = [name],
cluster = cluster,
namespace = namespace,
app_grp = app_grp,
gitops_path = gitops_path,
strip_prefixes = [
namespace + "-",
Expand Down
20 changes: 16 additions & 4 deletions skylib/kustomize/kustomize.bzl
Original file line numberDiff line numberDiff line change
Expand Up@@ -440,19 +440,30 @@ fi
""".format(push_statements)

namespace = ctx.attr.namespace
app_grp = ctx.attr.app_grp

# Construct the path with optional app_grp
if app_grp:
path_template = "{gitops_path}/{app_grp}/{namespace}/{cluster}/{file}"
mkdir_template = "{gitops_path}/{app_grp}/{namespace}/{cluster}"
else:
path_template = "{gitops_path}/{namespace}/{cluster}/{file}"
mkdir_template = "{gitops_path}/{namespace}/{cluster}"

for inattr in ctx.attr.srcs:
if "{" in namespace:
fail("unable to gitops namespace with placeholders %s" % inattr.label) #mynamespace should not be gitopsed
for infile in inattr.files.to_list():
statements += ("echo $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n" +
"mkdir -p $TARGET_DIR/{gitops_path}/{namespace}/{cluster}\n" +
"echo '# GENERATED BY {rulename} -> {gitopsrulename}' > $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n" +
"{template_engine} --template={infile} --variable=NAMESPACE={namespace} --stamp_info_file={info_file} >> $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n").format(
statements += ("echo $TARGET_DIR/" + path_template + "\n" +
"mkdir -p $TARGET_DIR/" + mkdir_template + "\n" +
"echo '# GENERATED BY {rulename} -> {gitopsrulename}' > $TARGET_DIR/" + path_template + "\n" +
"{template_engine} --template={infile} --variable=NAMESPACE={namespace} --stamp_info_file={info_file} >> $TARGET_DIR/" + path_template + "\n").format(
infile = infile.path,
rulename = inattr.label,
gitopsrulename = ctx.label,
namespace = namespace,
gitops_path = ctx.attr.gitops_path,
app_grp = app_grp,
cluster = cluster,
file = _remove_prefixes(infile.path.split("/")[-1], strip_prefixes),
template_engine = "${RUNFILES}/%s" % _get_runfile_path(ctx, ctx.executable._template_engine),
Expand DownExpand Up@@ -485,6 +496,7 @@ gitops = rule(
"srcs": attr.label_list(providers = (KustomizeInfo,)),
"cluster": attr.string(mandatory = True),
"namespace": attr.string(mandatory = True),
"app_grp": attr.string(doc = "optional application group to insert between gitops_path and namespace in the file path"),
"deployment_branch": attr.string(),
"gitops_path": attr.string(),
"release_branch_prefix": attr.string(),
Expand Down
51 changes: 51 additions & 0 deletions skylib/kustomize/tests/BUILD
Original file line numberDiff line numberDiff line change
Expand Up@@ -270,6 +270,57 @@ gitops(
namespace = "test",
)

# Test gitops with app_grp parameter
gitops(
name = "dev-something-with-app-grp.gitops",
testonly = True,
srcs = [":namespace_test"],
app_grp = "backend",
cluster = "dev",
gitops_path = "cloud",
namespace = "test",
)

# Test gitops without app_grp (should behave like original)
gitops(
name = "dev-something-no-app-grp.gitops",
testonly = True,
srcs = [":namespace_test"],
cluster = "dev",
gitops_path = "cloud",
namespace = "test",
# app_grp intentionally omitted to test backward compatibility
)

# Test rules to verify gitops output with app_grp
rule_test(
name = "gitops_with_app_grp_generates_executable",
generates = ["dev-something-with-app-grp.gitops"],
rule = "dev-something-with-app-grp.gitops",
)

# Test rules to verify gitops output without app_grp (backward compatibility)
rule_test(
name = "gitops_no_app_grp_generates_executable",
generates = ["dev-something-no-app-grp.gitops"],
rule = "dev-something-no-app-grp.gitops",
)

# File tests to verify gitops path generation
file_test(
name = "gitops_with_app_grp_path_test",
file = ":dev-something-with-app-grp.gitops",
matches = 4, # Should appear in echo, mkdir, echo comment, and template_engine commands
regexp = "cloud/backend",
)

file_test(
name = "gitops_no_app_grp_path_test",
file = ":dev-something-no-app-grp.gitops",
matches = 4, # Should appear in echo, mkdir, echo comment, and template_engine commands
regexp = "cloud/test/dev",
)

#-------------------
kustomize(
name = "name_prefix",
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,6 +86,7 @@ When you run `bazel run ///helloworld:mynamespace.apply`, it applies this file i
| ***release_branch_prefix*** | `master` | A git branch name/prefix. Automatically run GitOps while building this branch. See [GitOps and Deployment](#gitops_and_deployment).
| ***deployment_branch*** | `None` | Automatic GitOps output will appear in a branch and PR with this name. See [GitOps and Deployment](#gitops_and_deployment).
| ***gitops_path*** | `cloud` | Path within the git repo where gitops files get generated into
| ***app_grp*** | `` | Optional folder for grouping apps after gitops_path in git repo
| ***tags*** | `[]` | See [Bazel docs on tags](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).
| ***visibility*** | [Default_visibility](https://docs.bazel.build/versions/master/be/functions.html#package.default_visibility) | Changes the visibility of all rules generated by this macro. See [Bazel docs on visibility](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).

Expand Down
4 changes: 4 additions & 0 deletions examples/e2e-test.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,7 @@ rm -rf cloud
bazel run //helloworld:canary.gitops
bazel run //helloworld:release.gitops
bazel run //helloworld:gitops_custom_path.gitops
bazel run //helloworld:gitops_with_app_grp.gitops
#the result of .gitops operation goes into /cloud directory and should be submitted back to the repo

#apply everything generated
Expand All@@ -48,5 +49,8 @@ kubectl apply -f cloud -R
#apply gitops_custom_path gen
kubectl apply -f custom_cloud -R

#apply gitops_with_app_grp gen (should create cloud/backend/hwteam/kind-kind/ structure)
kubectl apply -f cloud/backend -R

#wait for readiness
kubectl -n hwteam wait --timeout=60s --for=condition=Available deployment/helloworld deployment/helloworld-canary deployment/helloworld-gitops-custom-path
20 changes: 20 additions & 0 deletions examples/helloworld/BUILD
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,6 +123,26 @@ k8s_deploy(
user = USER,
)

k8s_deploy(
name = "gitops_with_app_grp",
app_grp = "backend", # This will create path: cloud/backend/hwteam/kind-kind/gitops_with_app_grp.yaml
cluster = CLUSTER,
deployment_branch = "helloworld-gitops-app-grp",
# image_digest_tag = True, # test optional image tagging
# image_registry = REGISTRY, # override the default registry host for production
# image_repository_prefix = "k8s",
images = {
"helloworld-image": ":image",
},
manifests = [
"deployment.yaml",
"service.yaml",
],
name_suffix = "-gitops-app-grp",
namespace = NAMESPACE,
user = USER,
)

sh_test(
name = "k8s_deploy_test",
srcs = ["k8s_deploy_test.sh"],
Expand Down
2 changes: 2 additions & 0 deletions skylib/k8s.bzl
Original file line numberDiff line numberDiff line change
Expand Up@@ -111,6 +111,7 @@ def k8s_deploy(
cluster = "dev",
user = "{BUILD_USER}",
namespace = None,
app_grp = None, # optional application group to insert between gitops_path and namespace in the file path
configmaps_srcs = None,
secrets_srcs = None,
configmaps_renaming = None, # configmaps renaming policy. Could be None or 'hash'.
Expand DownExpand Up@@ -279,6 +280,7 @@ def k8s_deploy(
srcs = [name],
cluster = cluster,
namespace = namespace,
app_grp = app_grp,
gitops_path = gitops_path,
strip_prefixes = [
namespace + "-",
Expand Down
20 changes: 16 additions & 4 deletions skylib/kustomize/kustomize.bzl
Original file line numberDiff line numberDiff line change
Expand Up@@ -440,19 +440,30 @@ fi
""".format(push_statements)

namespace = ctx.attr.namespace
app_grp = ctx.attr.app_grp

# Construct the path with optional app_grp
if app_grp:
path_template = "{gitops_path}/{app_grp}/{namespace}/{cluster}/{file}"
mkdir_template = "{gitops_path}/{app_grp}/{namespace}/{cluster}"
else:
path_template = "{gitops_path}/{namespace}/{cluster}/{file}"
mkdir_template = "{gitops_path}/{namespace}/{cluster}"

for inattr in ctx.attr.srcs:
if "{" in namespace:
fail("unable to gitops namespace with placeholders %s" % inattr.label) #mynamespace should not be gitopsed
for infile in inattr.files.to_list():
statements += ("echo $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n" +
"mkdir -p $TARGET_DIR/{gitops_path}/{namespace}/{cluster}\n" +
"echo '# GENERATED BY {rulename} -> {gitopsrulename}' > $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n" +
"{template_engine} --template={infile} --variable=NAMESPACE={namespace} --stamp_info_file={info_file} >> $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n").format(
statements += ("echo $TARGET_DIR/" + path_template + "\n" +
"mkdir -p $TARGET_DIR/" + mkdir_template + "\n" +
"echo '# GENERATED BY {rulename} -> {gitopsrulename}' > $TARGET_DIR/" + path_template + "\n" +
"{template_engine} --template={infile} --variable=NAMESPACE={namespace} --stamp_info_file={info_file} >> $TARGET_DIR/" + path_template + "\n").format(
infile = infile.path,
rulename = inattr.label,
gitopsrulename = ctx.label,
namespace = namespace,
gitops_path = ctx.attr.gitops_path,
app_grp = app_grp,
cluster = cluster,
file = _remove_prefixes(infile.path.split("/")[-1], strip_prefixes),
template_engine = "${RUNFILES}/%s" % _get_runfile_path(ctx, ctx.executable._template_engine),
Expand DownExpand Up@@ -485,6 +496,7 @@ gitops = rule(
"srcs": attr.label_list(providers = (KustomizeInfo,)),
"cluster": attr.string(mandatory = True),
"namespace": attr.string(mandatory = True),
"app_grp": attr.string(doc = "optional application group to insert between gitops_path and namespace in the file path"),
"deployment_branch": attr.string(),
"gitops_path": attr.string(),
"release_branch_prefix": attr.string(),
Expand Down
51 changes: 51 additions & 0 deletions skylib/kustomize/tests/BUILD
Original file line numberDiff line numberDiff line change
Expand Up@@ -270,6 +270,57 @@ gitops(
namespace = "test",
)

# Test gitops with app_grp parameter
gitops(
name = "dev-something-with-app-grp.gitops",
testonly = True,
srcs = [":namespace_test"],
app_grp = "backend",
cluster = "dev",
gitops_path = "cloud",
namespace = "test",
)

# Test gitops without app_grp (should behave like original)
gitops(
name = "dev-something-no-app-grp.gitops",
testonly = True,
srcs = [":namespace_test"],
cluster = "dev",
gitops_path = "cloud",
namespace = "test",
# app_grp intentionally omitted to test backward compatibility
)

# Test rules to verify gitops output with app_grp
rule_test(
name = "gitops_with_app_grp_generates_executable",
generates = ["dev-something-with-app-grp.gitops"],
rule = "dev-something-with-app-grp.gitops",
)

# Test rules to verify gitops output without app_grp (backward compatibility)
rule_test(
name = "gitops_no_app_grp_generates_executable",
generates = ["dev-something-no-app-grp.gitops"],
rule = "dev-something-no-app-grp.gitops",
)

# File tests to verify gitops path generation
file_test(
name = "gitops_with_app_grp_path_test",
file = ":dev-something-with-app-grp.gitops",
matches = 4, # Should appear in echo, mkdir, echo comment, and template_engine commands
regexp = "cloud/backend",
)

file_test(
name = "gitops_no_app_grp_path_test",
file = ":dev-something-no-app-grp.gitops",
matches = 4, # Should appear in echo, mkdir, echo comment, and template_engine commands
regexp = "cloud/test/dev",
)

#-------------------
kustomize(
name = "name_prefix",
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,6 +86,7 @@ When you run `bazel run ///helloworld:mynamespace.apply`, it applies this file i
| ***release_branch_prefix*** | `master` | A git branch name/prefix. Automatically run GitOps while building this branch. See [GitOps and Deployment](#gitops_and_deployment).
| ***deployment_branch*** | `None` | Automatic GitOps output will appear in a branch and PR with this name. See [GitOps and Deployment](#gitops_and_deployment).
| ***gitops_path*** | `cloud` | Path within the git repo where gitops files get generated into
| ***app_grp*** | `` | Optional folder for grouping apps after gitops_path in git repo
| ***tags*** | `[]` | See [Bazel docs on tags](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).
| ***visibility*** | [Default_visibility](https://docs.bazel.build/versions/master/be/functions.html#package.default_visibility) | Changes the visibility of all rules generated by this macro. See [Bazel docs on visibility](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).

Expand Down
4 changes: 4 additions & 0 deletions examples/e2e-test.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,7 @@ rm -rf cloud
bazel run //helloworld:canary.gitops
bazel run //helloworld:release.gitops
bazel run //helloworld:gitops_custom_path.gitops
bazel run //helloworld:gitops_with_app_grp.gitops
#the result of .gitops operation goes into /cloud directory and should be submitted back to the repo

#apply everything generated
Expand All@@ -48,5 +49,8 @@ kubectl apply -f cloud -R
#apply gitops_custom_path gen
kubectl apply -f custom_cloud -R

#apply gitops_with_app_grp gen (should create cloud/backend/hwteam/kind-kind/ structure)
kubectl apply -f cloud/backend -R

#wait for readiness
kubectl -n hwteam wait --timeout=60s --for=condition=Available deployment/helloworld deployment/helloworld-canary deployment/helloworld-gitops-custom-path
20 changes: 20 additions & 0 deletions examples/helloworld/BUILD
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,6 +123,26 @@ k8s_deploy(
user = USER,
)

k8s_deploy(
name = "gitops_with_app_grp",
app_grp = "backend", # This will create path: cloud/backend/hwteam/kind-kind/gitops_with_app_grp.yaml
cluster = CLUSTER,
deployment_branch = "helloworld-gitops-app-grp",
# image_digest_tag = True, # test optional image tagging
# image_registry = REGISTRY, # override the default registry host for production
# image_repository_prefix = "k8s",
images = {
"helloworld-image": ":image",
},
manifests = [
"deployment.yaml",
"service.yaml",
],
name_suffix = "-gitops-app-grp",
namespace = NAMESPACE,
user = USER,
)

sh_test(
name = "k8s_deploy_test",
srcs = ["k8s_deploy_test.sh"],
Expand Down
2 changes: 2 additions & 0 deletions skylib/k8s.bzl
Original file line numberDiff line numberDiff line change
Expand Up@@ -111,6 +111,7 @@ def k8s_deploy(
cluster = "dev",
user = "{BUILD_USER}",
namespace = None,
app_grp = None, # optional application group to insert between gitops_path and namespace in the file path
configmaps_srcs = None,
secrets_srcs = None,
configmaps_renaming = None, # configmaps renaming policy. Could be None or 'hash'.
Expand DownExpand Up@@ -279,6 +280,7 @@ def k8s_deploy(
srcs = [name],
cluster = cluster,
namespace = namespace,
app_grp = app_grp,
gitops_path = gitops_path,
strip_prefixes = [
namespace + "-",
Expand Down
20 changes: 16 additions & 4 deletions skylib/kustomize/kustomize.bzl
Original file line numberDiff line numberDiff line change
Expand Up@@ -440,19 +440,30 @@ fi
""".format(push_statements)

namespace = ctx.attr.namespace
app_grp = ctx.attr.app_grp

# Construct the path with optional app_grp
if app_grp:
path_template = "{gitops_path}/{app_grp}/{namespace}/{cluster}/{file}"
mkdir_template = "{gitops_path}/{app_grp}/{namespace}/{cluster}"
else:
path_template = "{gitops_path}/{namespace}/{cluster}/{file}"
mkdir_template = "{gitops_path}/{namespace}/{cluster}"

for inattr in ctx.attr.srcs:
if "{" in namespace:
fail("unable to gitops namespace with placeholders %s" % inattr.label) #mynamespace should not be gitopsed
for infile in inattr.files.to_list():
statements += ("echo $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n" +
"mkdir -p $TARGET_DIR/{gitops_path}/{namespace}/{cluster}\n" +
"echo '# GENERATED BY {rulename} -> {gitopsrulename}' > $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n" +
"{template_engine} --template={infile} --variable=NAMESPACE={namespace} --stamp_info_file={info_file} >> $TARGET_DIR/{gitops_path}/{namespace}/{cluster}/{file}\n").format(
statements += ("echo $TARGET_DIR/" + path_template + "\n" +
"mkdir -p $TARGET_DIR/" + mkdir_template + "\n" +
"echo '# GENERATED BY {rulename} -> {gitopsrulename}' > $TARGET_DIR/" + path_template + "\n" +
"{template_engine} --template={infile} --variable=NAMESPACE={namespace} --stamp_info_file={info_file} >> $TARGET_DIR/" + path_template + "\n").format(
infile = infile.path,
rulename = inattr.label,
gitopsrulename = ctx.label,
namespace = namespace,
gitops_path = ctx.attr.gitops_path,
app_grp = app_grp,
cluster = cluster,
file = _remove_prefixes(infile.path.split("/")[-1], strip_prefixes),
template_engine = "${RUNFILES}/%s" % _get_runfile_path(ctx, ctx.executable._template_engine),
Expand DownExpand Up@@ -485,6 +496,7 @@ gitops = rule(
"srcs": attr.label_list(providers = (KustomizeInfo,)),
"cluster": attr.string(mandatory = True),
"namespace": attr.string(mandatory = True),
"app_grp": attr.string(doc = "optional application group to insert between gitops_path and namespace in the file path"),
"deployment_branch": attr.string(),
"gitops_path": attr.string(),
"release_branch_prefix": attr.string(),
Expand Down
51 changes: 51 additions & 0 deletions skylib/kustomize/tests/BUILD
Original file line numberDiff line numberDiff line change
Expand Up@@ -270,6 +270,57 @@ gitops(
namespace = "test",
)

# Test gitops with app_grp parameter
gitops(
name = "dev-something-with-app-grp.gitops",
testonly = True,
srcs = [":namespace_test"],
app_grp = "backend",
cluster = "dev",
gitops_path = "cloud",
namespace = "test",
)

# Test gitops without app_grp (should behave like original)
gitops(
name = "dev-something-no-app-grp.gitops",
testonly = True,
srcs = [":namespace_test"],
cluster = "dev",
gitops_path = "cloud",
namespace = "test",
# app_grp intentionally omitted to test backward compatibility
)

# Test rules to verify gitops output with app_grp
rule_test(
name = "gitops_with_app_grp_generates_executable",
generates = ["dev-something-with-app-grp.gitops"],
rule = "dev-something-with-app-grp.gitops",
)

# Test rules to verify gitops output without app_grp (backward compatibility)
rule_test(
name = "gitops_no_app_grp_generates_executable",
generates = ["dev-something-no-app-grp.gitops"],
rule = "dev-something-no-app-grp.gitops",
)

# File tests to verify gitops path generation
file_test(
name = "gitops_with_app_grp_path_test",
file = ":dev-something-with-app-grp.gitops",
matches = 4, # Should appear in echo, mkdir, echo comment, and template_engine commands
regexp = "cloud/backend",
)

file_test(
name = "gitops_no_app_grp_path_test",
file = ":dev-something-no-app-grp.gitops",
matches = 4, # Should appear in echo, mkdir, echo comment, and template_engine commands
regexp = "cloud/test/dev",
)

#-------------------
kustomize(
name = "name_prefix",
Expand Down