Skip to content

Commit aeaa56d

Browse files
Sync one tool update
Signed-off-by: Lukasz Gryglicki <lgryglicki@cncf.io> Assisted by [OpenAI](https://platform.openai.com/) Assisted by [GitHub Copilot](https://github.com/features/copilot)
1 parent b1b0b3c commit aeaa56d

1 file changed

Lines changed: 163 additions & 7 deletions

File tree

utils/skip_cla_entry.sh

Lines changed: 163 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
#!/bin/bash
2+
#
3+
# Note: data returned from "scan.sh" has escape characters, like '\\`, use `\` when putting that data back to DynamoDB (via this script) to avoid double escaping.
4+
#
25
# MODE=mode ./utils/skip_cla_entry.sh sun-test-org '*' 'patterns'
3-
# put-item Overwrites/adds the entire `skip_cla` entry.
4-
# add-key Adds or updates a key/value inside the skip_cla map (preserves other keys)
5-
# delete-key Removes a key from the skip_cla map
6-
# delete-item Deletes the entire `skip_cla` entry.
6+
# put-item Overwrites/adds the entire `skip_cla` entry.
7+
# add-key Adds or updates a key/value inside the skip_cla map (preserves other keys)
8+
# delete-key Removes a key from the skip_cla map
9+
# delete-item Deletes the entire `skip_cla` entry.
10+
# add-key-item Adds one pattern item into an existing skip_cla key array (idempotent)
11+
# delete-key-item Removes one pattern item from an existing skip_cla key array (idempotent)
712
#
813
# MODE=add-key ./utils/skip_cla_entry.sh sun-test-org 'repo1' 're:vee?rendra;*;*'
914
# MODE=add-key ./utils/skip_cla_entry.sh 'sun-test-org' 'repo1' 'lukaszgryglicki;re:gryglicki'
@@ -16,10 +21,12 @@
1621
# STAGE=dev MODE=add-key ./utils/skip_cla_entry.sh 'openfga' 'vscode-ext' 'Copilot;re:^\d+\+Copilot@users\.noreply\.github\.com$;copilot-swe-agent[bot]'
1722
# STAGE=prod MODE=add-key DEBUG=1 ./utils/skip_cla_entry.sh 'open-telemetry' 'opentelemetry-rust' '*;re:^\d+\+Copilot@users\.noreply\.github\.com$;copilot-swe-agent[bot]'
1823
# STAGE=prod MODE=add-key ./utils/skip_cla_entry.sh 'openfga' 'vscode-ext' '[Copilot;re:^\d+\+Copilot@users\.noreply\.github\.com$;copilot-swe-agent[bot]||;re:^\d+\+Copilot@users\.noreply\.github\.com$;copilot-swe-agent[bot]]'
24+
# STAGE=prod MODE=add-key-item ./utils/skip_cla_entry.sh 'openfga' '*' 're:(?i)^copilot$;re:(?i)^\d+\+copilot@users\.noreply\.github\.com$;*'
25+
# STAGE=prod MODE=delete-key-item ./utils/skip_cla_entry.sh 'openfga' '*' 're:(?i)^copilot$;re:(?i)^\d+\+copilot@users\.noreply\.github\.com$;*'
1926

2027
if [ -z "$MODE" ]
2128
then
22-
echo "$0: MODE must be set, valid values are: put-item, add-key, delete-key, delete-item"
29+
echo "$0: MODE must be set, valid values are: put-item, add-key, delete-key, delete-item, add-key-item, delete-key-item"
2330
exit 1
2431
fi
2532

@@ -30,6 +37,89 @@ if [ -z "$REGION" ]; then
3037
REGION='us-east-1'
3138
fi
3239

40+
aws_key_json() {
41+
jq -cn --arg org "$1" '{"organization_name": {"S": $org}}'
42+
}
43+
44+
aws_attr_names_json() {
45+
jq -cn --arg repo "$1" '{"#repo": $repo}'
46+
}
47+
48+
aws_attr_value_string_json() {
49+
jq -cn --arg val "$1" '{":val": {"S": $val}}'
50+
}
51+
52+
get_skip_cla_key_value() {
53+
local org="$1"
54+
local repo="$2"
55+
local raw
56+
57+
if ! raw="$(
58+
aws --profile "lfproduct-${STAGE}" --region "${REGION}" dynamodb get-item \
59+
--table-name "cla-${STAGE}-github-orgs" \
60+
--key "$(aws_key_json "$org")" \
61+
--projection-expression 'skip_cla'
62+
)"; then
63+
echo "Error: failed to fetch skip_cla value from DynamoDB for organization='${org}', repo='${repo}'" >&2
64+
return 1
65+
fi
66+
67+
if ! jq -r --arg repo "$repo" '.Item.skip_cla.M[$repo].S // empty' <<<"$raw"; then
68+
echo "Error: failed to parse skip_cla value from DynamoDB for organization='${org}', repo='${repo}'" >&2
69+
return 1
70+
fi
71+
}
72+
73+
modify_skip_cla_array_value() {
74+
local current="$1"
75+
local action="$2"
76+
local item="$3"
77+
CURRENT="$current" ACTION="$action" ITEM="$item" python3 - <<'PY'
78+
import os
79+
80+
current = os.environ.get("CURRENT", "")
81+
action = os.environ["ACTION"]
82+
item_raw = os.environ.get("ITEM", "")
83+
84+
def parse_flat_value(value: str):
85+
value = (value or "").strip()
86+
if not value:
87+
return []
88+
if value.startswith("["):
89+
if not value.endswith("]"):
90+
raise SystemExit("malformed array value: missing closing ]")
91+
inner = value[1:-1]
92+
parts = inner.split("||") if inner else []
93+
else:
94+
parts = [value]
95+
return [p.strip() for p in parts if p.strip()]
96+
97+
items = parse_flat_value(current)
98+
item_values = parse_flat_value(item_raw)
99+
changed = False
100+
101+
if action == "add":
102+
for item in item_values:
103+
if item not in items:
104+
items.append(item)
105+
changed = True
106+
elif action == "delete":
107+
if item_values:
108+
item_set = set(item_values)
109+
new_items = [p for p in items if p not in item_set]
110+
changed = (new_items != items)
111+
items = new_items
112+
else:
113+
raise SystemExit(f"unsupported action: {action}")
114+
115+
new_value = "" if not items else "[" + "||".join(items) + "]"
116+
117+
print("changed=true" if changed else "changed=false")
118+
print("delete_key=true" if changed and new_value == "" else "delete_key=false")
119+
print(f"new_value={new_value}")
120+
PY
121+
}
122+
33123
case "$MODE" in
34124
put-item)
35125
if ( [ -z "${1}" ] || [ -z "${2}" ] || [ -z "${3}" ] ); then
@@ -80,9 +170,76 @@ case "$MODE" in
80170
--key '{\"organization_name\": {\"S\": \"${1}\"}}' \
81171
--update-expression 'REMOVE skip_cla'"
82172
;;
173+
add-key-item|delete-key-item)
174+
if ( [ -z "${1}" ] || [ -z "${2}" ] || [ -z "${3}" ] ); then
175+
echo "Usage: $0 <organization_name> <repo or re:repo-regexp or *> <pattern-item>"
176+
exit 1
177+
fi
178+
179+
org_name="${1}"
180+
repo_key="${2}"
181+
item_value="${3}"
182+
if ! current_value="$(get_skip_cla_key_value "$org_name" "$repo_key")"; then
183+
exit 1
184+
fi
185+
186+
if [ "$MODE" = "add-key-item" ]; then
187+
action="add"
188+
else
189+
action="delete"
190+
fi
191+
192+
if ! helper_output="$(modify_skip_cla_array_value "$current_value" "$action" "$item_value")"; then
193+
echo "Error: failed to modify skip_cla value for organization='${org_name}', repo='${repo_key}', mode='${MODE}'" >&2
194+
exit 1
195+
fi
196+
197+
mapfile -t result_lines <<<"$helper_output"
198+
if [ "${#result_lines[@]}" -ne 3 ] || [[ "${result_lines[0]}" != changed=* ]] || [[ "${result_lines[1]}" != delete_key=* ]] || [[ "${result_lines[2]}" != new_value=* ]]; then
199+
echo "Error: unexpected output from modify_skip_cla_array_value" >&2
200+
if [ ! -z "$DEBUG" ]; then
201+
echo "DEBUG: organization='${org_name}', repo='${repo_key}', mode='${MODE}', action='${action}', item='${item_value}'" >&2
202+
echo "DEBUG: helper_output='${helper_output}'" >&2
203+
fi
204+
exit 1
205+
fi
206+
changed="${result_lines[0]#changed=}"
207+
delete_key="${result_lines[1]#delete_key=}"
208+
new_value="${result_lines[2]#new_value=}"
209+
210+
if [ "$changed" != "true" ]; then
211+
if [ ! -z "$DEBUG" ]; then
212+
echo "No changes needed for organization='${org_name}', repo='${repo_key}', mode='${MODE}'"
213+
fi
214+
exit 0
215+
fi
216+
217+
if [ "$delete_key" = "true" ]; then
218+
if [ ! -z "$DEBUG" ]; then
219+
echo "aws --profile \"lfproduct-${STAGE}\" --region \"${REGION}\" dynamodb update-item --table-name \"cla-${STAGE}-github-orgs\" --key \"$(aws_key_json "$org_name")\" --update-expression 'REMOVE skip_cla.#repo' --expression-attribute-names \"$(aws_attr_names_json "$repo_key")\""
220+
fi
221+
aws --profile "lfproduct-${STAGE}" --region "${REGION}" dynamodb update-item \
222+
--table-name "cla-${STAGE}-github-orgs" \
223+
--key "$(aws_key_json "$org_name")" \
224+
--update-expression 'REMOVE skip_cla.#repo' \
225+
--expression-attribute-names "$(aws_attr_names_json "$repo_key")"
226+
exit $?
227+
fi
228+
229+
if [ ! -z "$DEBUG" ]; then
230+
echo "aws --profile \"lfproduct-${STAGE}\" --region \"${REGION}\" dynamodb update-item --table-name \"cla-${STAGE}-github-orgs\" --key \"$(aws_key_json "$org_name")\" --update-expression 'SET skip_cla.#repo = :val' --expression-attribute-names \"$(aws_attr_names_json "$repo_key")\" --expression-attribute-values \"$(aws_attr_value_string_json "$new_value")\""
231+
fi
232+
aws --profile "lfproduct-${STAGE}" --region "${REGION}" dynamodb update-item \
233+
--table-name "cla-${STAGE}-github-orgs" \
234+
--key "$(aws_key_json "$org_name")" \
235+
--update-expression 'SET skip_cla.#repo = :val' \
236+
--expression-attribute-names "$(aws_attr_names_json "$repo_key")" \
237+
--expression-attribute-values "$(aws_attr_value_string_json "$new_value")"
238+
exit $?
239+
;;
83240
*)
84241
echo "$0: Unknown MODE: $MODE"
85-
echo "Valid values are: put-item, add-key, delete-key, delete-item"
242+
echo "Valid values are: put-item, add-key, delete-key, delete-item, add-key-item, delete-key-item"
86243
exit 1
87244
;;
88245
esac
@@ -93,4 +250,3 @@ then
93250
fi
94251

95252
eval $CMD
96-

0 commit comments

Comments
 (0)