@jfrog/opencode-jfrog-plugin 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +105 -51
  2. package/dist/index.js +30 -240
  3. package/package.json +6 -6
  4. package/skills/jfrog/SKILL.md +529 -0
  5. package/skills/jfrog/assets/.gitkeep +0 -0
  6. package/skills/jfrog/references/apptrust-entities.md +154 -0
  7. package/skills/jfrog/references/artifactory-api-gaps.md +206 -0
  8. package/skills/jfrog/references/artifactory-aql-syntax.md +656 -0
  9. package/skills/jfrog/references/artifactory-entities.md +236 -0
  10. package/skills/jfrog/references/artifactory-operations.md +178 -0
  11. package/skills/jfrog/references/catalog-entities.md +219 -0
  12. package/skills/jfrog/references/general-bulk-operations-and-agent-patterns.md +93 -0
  13. package/skills/jfrog/references/general-parallel-execution.md +131 -0
  14. package/skills/jfrog/references/general-use-case-hints.md +27 -0
  15. package/skills/jfrog/references/jfrog-brand-html-report.md +98 -0
  16. package/skills/jfrog/references/jfrog-cli-install-upgrade.md +30 -0
  17. package/skills/jfrog/references/jfrog-entity-index.md +112 -0
  18. package/skills/jfrog/references/jfrog-login-flow.md +132 -0
  19. package/skills/jfrog/references/jfrog-url-references.md +51 -0
  20. package/skills/jfrog/references/onemodel-common-patterns.md +323 -0
  21. package/skills/jfrog/references/onemodel-graphql.md +446 -0
  22. package/skills/jfrog/references/onemodel-query-examples.md +753 -0
  23. package/skills/jfrog/references/platform-access-entities.md +200 -0
  24. package/skills/jfrog/references/platform-admin-api-gaps.md +164 -0
  25. package/skills/jfrog/references/platform-admin-operations.md +58 -0
  26. package/skills/jfrog/references/projects-api.md +241 -0
  27. package/skills/jfrog/references/release-lifecycle-entities.md +180 -0
  28. package/skills/jfrog/references/stored-packages-entities.md +165 -0
  29. package/skills/jfrog/references/xray-entities.md +740 -0
  30. package/skills/jfrog/scripts/check-environment.sh +224 -0
  31. package/skills/jfrog/scripts/jfrog-login-register-session.sh +84 -0
  32. package/skills/jfrog/scripts/jfrog-login-save-credentials.sh +128 -0
  33. package/skills/jfrog-package-safety-and-download/SKILL.md +275 -0
  34. package/sync-skills-vendor.json +5 -0
@@ -0,0 +1,224 @@
1
+ #!/usr/bin/env bash
2
+ # check-environment.sh — Cached JFrog CLI environment check
3
+ #
4
+ # Checks if jf is installed and its version, using a 24h-TTL cache
5
+ # at ${JFROG_CLI_HOME_DIR:-$HOME/.jfrog}/skills-cache/jfrog-skill-state.json
6
+ # to avoid redundant checks. The skills-cache/ dir holds only this file and
7
+ # the OneModel schema cache — not temp API output.
8
+ #
9
+ # Usage:
10
+ # bash check-environment.sh [<model-slug>] [--force]
11
+ #
12
+ # stdout: bare JFROG_CLI_USER_AGENT value (one line) — agent captures it
13
+ # and runs `export JFROG_CLI_USER_AGENT='<v>'` once at the top of
14
+ # every bash invocation that calls jf
15
+ # stderr: JSON state (informational, also written to cache file)
16
+ #
17
+ # Exit codes:
18
+ # 0 — cache fresh, CLI ready
19
+ # 1 — cache refreshed, CLI ready
20
+ # 2 — jf not installed
21
+ # 3 — jf below MIN_CLI_VERSION (required for `jf api`)
22
+
23
+ set -euo pipefail
24
+
25
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
26
+ SKILL_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
27
+ JFROG_HOME="${JFROG_CLI_HOME_DIR:-$HOME/.jfrog}"
28
+ CACHE_DIR="$JFROG_HOME/skills-cache"
29
+ CACHE_FILE="$CACHE_DIR/jfrog-skill-state.json"
30
+ DEFAULT_TTL_HOURS=24
31
+ FORCE=false
32
+
33
+ # Minimum jf CLI version required by this skill. `jf api` (the generic
34
+ # authenticated REST pass-through used by nearly every reference in this
35
+ # skill) landed in 2.100.0; older CLIs fail with "unknown command: api".
36
+ MIN_CLI_VERSION="2.100.0"
37
+
38
+ MODEL_SLUG=""
39
+ for arg in "$@"; do
40
+ if [[ "$arg" == "--force" ]]; then
41
+ FORCE=true
42
+ elif [[ -z "$MODEL_SLUG" ]]; then
43
+ MODEL_SLUG="$arg"
44
+ fi
45
+ done
46
+
47
+ now_epoch() {
48
+ date -u +%s
49
+ }
50
+
51
+ iso_now() {
52
+ date -u '+%Y-%m-%dT%H:%M:%SZ'
53
+ }
54
+
55
+ # Returns 0 if $1 is strictly less than $2 (semver via sort -V).
56
+ version_lt() {
57
+ [[ "$1" == "$2" ]] && return 1
58
+ [[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -1)" == "$1" ]]
59
+ }
60
+
61
+ emit_min_version_error() {
62
+ local v="$1"
63
+ cat >&2 <<EOF
64
+ {"error": "jf CLI $v is below minimum $MIN_CLI_VERSION required by this skill (needed for 'jf api'). See references/jfrog-cli-install-upgrade.md."}
65
+ EOF
66
+ }
67
+
68
+ is_cache_fresh() {
69
+ if [[ ! -f "$CACHE_FILE" ]]; then
70
+ return 1
71
+ fi
72
+
73
+ if ! command -v jq &>/dev/null; then
74
+ return 1
75
+ fi
76
+
77
+ local checked_at ttl_hours checked_epoch now ttl_seconds age
78
+ checked_at=$(jq -r '.checked_at // empty' "$CACHE_FILE" 2>/dev/null) || return 1
79
+ ttl_hours=$(jq -r '.ttl_hours // 24' "$CACHE_FILE" 2>/dev/null) || return 1
80
+
81
+ if [[ -z "$checked_at" ]]; then
82
+ return 1
83
+ fi
84
+
85
+ # Parse ISO timestamp to epoch (portable: try GNU date, then BSD date)
86
+ if checked_epoch=$(date -d "$checked_at" +%s 2>/dev/null); then
87
+ : # GNU date succeeded
88
+ elif checked_epoch=$(date -jf '%Y-%m-%dT%H:%M:%SZ' "$checked_at" +%s 2>/dev/null); then
89
+ : # BSD date succeeded
90
+ else
91
+ return 1
92
+ fi
93
+
94
+ now=$(now_epoch)
95
+ ttl_seconds=$((ttl_hours * 3600))
96
+ age=$((now - checked_epoch))
97
+
98
+ if (( age < ttl_seconds )); then
99
+ return 0
100
+ fi
101
+ return 1
102
+ }
103
+
104
+ check_cli() {
105
+ local cli_path cli_version
106
+
107
+ if ! cli_path=$(command -v jf 2>/dev/null); then
108
+ echo '{"cli_installed": false}' >&2
109
+ return 2
110
+ fi
111
+
112
+ cli_version=$(jf --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' || echo "unknown")
113
+
114
+ # Check for latest version (best-effort, non-blocking)
115
+ local latest_version="unknown"
116
+ if command -v curl &>/dev/null; then
117
+ latest_version=$(curl -sf --max-time 5 "https://releases.jfrog.io/artifactory/jfrog-cli/v2-jf/" 2>/dev/null \
118
+ | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | sort -V | tail -1 || echo "unknown")
119
+ fi
120
+
121
+ local meets_minimum="true"
122
+ if [[ "$cli_version" == "unknown" ]] || version_lt "$cli_version" "$MIN_CLI_VERSION"; then
123
+ meets_minimum="false"
124
+ fi
125
+
126
+ mkdir -p "$CACHE_DIR"
127
+ local state
128
+ state=$(cat <<EOF
129
+ {
130
+ "checked_at": "$(iso_now)",
131
+ "ttl_hours": $DEFAULT_TTL_HOURS,
132
+ "cli_installed": true,
133
+ "cli_path": "$cli_path",
134
+ "cli_version": "$cli_version",
135
+ "minimum_version": "$MIN_CLI_VERSION",
136
+ "meets_minimum_version": $meets_minimum,
137
+ "latest_version_available": "$latest_version"
138
+ }
139
+ EOF
140
+ )
141
+ echo "$state" > "$CACHE_FILE"
142
+ echo "$state" >&2
143
+ return 1
144
+ }
145
+
146
+ # Detect the calling harness from environment signals. Output is one of:
147
+ # claude, cursor, gemini, goose, copilot, codex, unknown — or empty
148
+ # string when no agent signal is present (direct CLI/CI invocation).
149
+ # Naming matches the JFrog CLI's DetectExecutionContext() vocabulary.
150
+ detect_harness() {
151
+ if [[ -n "${CLAUDECODE:-}" || -n "${CLAUDE_CODE_ENTRYPOINT:-}" ]]; then
152
+ echo "claude"
153
+ elif [[ -n "${CURSOR_AGENT:-}" || -n "${CURSOR_CLI:-}" || -n "${CURSOR_TRACE_ID:-}" ]]; then
154
+ echo "cursor"
155
+ elif [[ -n "${GEMINI_CLI:-}" ]]; then
156
+ echo "gemini"
157
+ elif [[ -n "${GOOSE_TERMINAL:-}" ]]; then
158
+ echo "goose"
159
+ elif [[ -n "${COPILOT_CLI:-}" ]]; then
160
+ echo "copilot"
161
+ elif [[ -n "${CODEX_CI:-}" || -n "${CODEX_THREAD_ID:-}" || -n "${CODEX_SANDBOX:-}" ]]; then
162
+ echo "codex"
163
+ elif [[ -n "${AGENT:-}" || -n "$MODEL_SLUG" ]]; then
164
+ # Agent invoked us but we can't name it.
165
+ echo "unknown"
166
+ fi
167
+ # No match → print nothing; emitter omits the parens block entirely.
168
+ }
169
+
170
+ # Emit skill-level env vars to stdout (for eval by the caller)
171
+ emit_skill_env() {
172
+ local skill_version cli_version ua harness
173
+ # Parse version from SKILL.md YAML frontmatter (metadata.version)
174
+ skill_version="$(awk '/^---$/{n++; next} n==1 && /^[[:space:]]*version:/{gsub(/["'"'"']/, "", $2); print $2; exit}' "$SKILL_ROOT/SKILL.md" 2>/dev/null | tr -d '[:space:]')"
175
+ skill_version="${skill_version:-unknown}"
176
+ cli_version=$(jq -r '.cli_version // "unknown"' "$CACHE_FILE" 2>/dev/null || echo "unknown")
177
+ harness=$(detect_harness)
178
+ # Build the parens block: semicolon-separated key=value pairs.
179
+ local meta=""
180
+ if [[ -n "$harness" ]]; then
181
+ meta="tool=${harness}"
182
+ fi
183
+ if [[ -n "$MODEL_SLUG" ]]; then
184
+ if [[ -n "$meta" ]]; then
185
+ meta="${meta}; model=${MODEL_SLUG}"
186
+ else
187
+ meta="model=${MODEL_SLUG}"
188
+ fi
189
+ fi
190
+ ua="jfrog-skills/${skill_version}"
191
+ if [[ -n "$meta" ]]; then
192
+ ua="${ua} (${meta})"
193
+ fi
194
+ ua="${ua} jfrog-cli-go/${cli_version}"
195
+ printf '%s\n' "$ua"
196
+ }
197
+
198
+ # Main
199
+ if [[ "$FORCE" == "false" ]] && is_cache_fresh; then
200
+ cat "$CACHE_FILE" >&2
201
+ # Re-evaluate the minimum on every run so a bumped MIN_CLI_VERSION
202
+ # is enforced without waiting for the 24h cache to expire.
203
+ cached_version=$(jq -r '.cli_version // "unknown"' "$CACHE_FILE" 2>/dev/null)
204
+ if [[ "$cached_version" != "unknown" ]] && version_lt "$cached_version" "$MIN_CLI_VERSION"; then
205
+ emit_min_version_error "$cached_version"
206
+ exit 3
207
+ fi
208
+ emit_skill_env
209
+ exit 0
210
+ fi
211
+
212
+ check_cli || exit_code=$?
213
+ exit_code=${exit_code:-0}
214
+ if (( exit_code == 2 )); then
215
+ exit 2
216
+ fi
217
+
218
+ refreshed_version=$(jq -r '.cli_version // "unknown"' "$CACHE_FILE" 2>/dev/null)
219
+ if [[ "$refreshed_version" != "unknown" ]] && version_lt "$refreshed_version" "$MIN_CLI_VERSION"; then
220
+ emit_min_version_error "$refreshed_version"
221
+ exit 3
222
+ fi
223
+ emit_skill_env
224
+ exit 1
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env bash
2
+ # jfrog-login-register-session.sh — Verify a JFrog server and start a web login session
3
+ #
4
+ # Pings the server, generates a session UUID, and registers it with
5
+ # the Access API for browser-based authentication (bootstrap HTTP via
6
+ # `jf api --url`).
7
+ #
8
+ # Usage:
9
+ # bash jfrog-login-register-session.sh <platform-url>
10
+ #
11
+ # Arguments:
12
+ # platform-url — Full JFrog Platform URL (e.g. https://mycompany.jfrog.io)
13
+ #
14
+ # Output (stdout, one key=value per line):
15
+ # SESSION_UUID=<uuid>
16
+ # VERIFY_CODE=<last 4 chars of uuid>
17
+ #
18
+ # Exit codes:
19
+ # 0 — Session registered successfully
20
+ # 1 — Missing arguments or prerequisites
21
+ # 2 — Server not reachable (ping failed)
22
+ # 3 — Session registration request failed
23
+
24
+ set -euo pipefail
25
+
26
+ jf_api_http_status() {
27
+ # Parses "Http Status: NNN" from jf api stderr.
28
+ local err_file="$1"
29
+ local line
30
+ line=$(grep -F 'Http Status:' "$err_file" 2>/dev/null | tail -1 || true)
31
+ if [[ "$line" =~ Http\ Status:\ ([0-9]+) ]]; then
32
+ echo "${BASH_REMATCH[1]}"
33
+ else
34
+ echo "0"
35
+ fi
36
+ }
37
+
38
+ JFROG_PLATFORM_URL="${1:-}"
39
+
40
+ if [[ -z "$JFROG_PLATFORM_URL" ]]; then
41
+ echo "Usage: bash $0 <platform-url>" >&2
42
+ exit 1
43
+ fi
44
+
45
+ JFROG_PLATFORM_URL="${JFROG_PLATFORM_URL%/}"
46
+
47
+ if ! command -v jf &>/dev/null; then
48
+ echo "ERROR: jf is not installed" >&2
49
+ exit 1
50
+ fi
51
+
52
+ if ! command -v uuidgen &>/dev/null; then
53
+ echo "ERROR: uuidgen is not installed" >&2
54
+ exit 1
55
+ fi
56
+
57
+ TMPERR="$(mktemp)"
58
+ trap 'rm -f "$TMPERR"' EXIT
59
+
60
+ # Verify server is reachable (unauthenticated ping)
61
+ if ! jf api /artifactory/api/system/ping --url "$JFROG_PLATFORM_URL" >/dev/null 2>"$TMPERR"; then
62
+ PING_CODE=$(jf_api_http_status "$TMPERR")
63
+ echo "ERROR: Server not reachable at ${JFROG_PLATFORM_URL} (HTTP ${PING_CODE})" >&2
64
+ exit 2
65
+ fi
66
+
67
+ # Generate session UUID
68
+ SESSION_UUID=$(uuidgen | tr '[:upper:]' '[:lower:]')
69
+ VERIFY_CODE=${SESSION_UUID: -4}
70
+
71
+ # Register the session with the Access API
72
+ : >"$TMPERR"
73
+ if ! jf api /access/api/v2/authentication/jfrog_client_login/request \
74
+ --url "$JFROG_PLATFORM_URL" \
75
+ -X POST \
76
+ -H "Content-Type: application/json" \
77
+ -d "{\"session\":\"${SESSION_UUID}\"}" >/dev/null 2>"$TMPERR"; then
78
+ REG_CODE=$(jf_api_http_status "$TMPERR")
79
+ echo "ERROR: Session registration failed (HTTP ${REG_CODE})" >&2
80
+ exit 3
81
+ fi
82
+
83
+ echo "SESSION_UUID=${SESSION_UUID}"
84
+ echo "VERIFY_CODE=${VERIFY_CODE}"
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env bash
2
+ # jfrog-login-save-credentials.sh — Complete web login by retrieving token and saving credentials
3
+ #
4
+ # Retrieves the one-time access token from a completed web login session,
5
+ # derives a server ID, saves the configuration via jf config, and verifies.
6
+ # Bootstrap token exchange uses `jf api --url` (before any server exists in
7
+ # `jf config`); verification uses `jf api` with --server-id.
8
+ #
9
+ # Leaves the current default `jf` server unchanged. Subsequent calls should
10
+ # pass `--server-id=<id>` explicitly (the SKILL.md "Server selection rules"
11
+ # require this anyway).
12
+ #
13
+ # IMPORTANT: The token endpoint is one-time-use. If this script fails after
14
+ # consuming the token (e.g. jf config write blocked by sandbox), the session
15
+ # is burned and login must restart from register-session.
16
+ #
17
+ # Usage:
18
+ # bash jfrog-login-save-credentials.sh <platform-url> <session-uuid>
19
+ #
20
+ # Arguments:
21
+ # platform-url — Full JFrog Platform URL (e.g. https://mycompany.jfrog.io)
22
+ # session-uuid — Session UUID from jfrog-login-register-session.sh output
23
+ #
24
+ # Output (stdout):
25
+ # SERVER_ID=<derived-server-id>
26
+ # Followed by the Artifactory version JSON on success.
27
+ #
28
+ # Exit codes:
29
+ # 0 — Login succeeded, credentials saved and verified
30
+ # 1 — Missing arguments or prerequisites
31
+ # 2 — Token retrieval failed (user may not have completed browser login)
32
+ # 3 — Empty token in response
33
+ # 4 — jf config save or verification failed
34
+
35
+ set -euo pipefail
36
+
37
+ jf_api_http_status() {
38
+ local err_file="$1"
39
+ local line
40
+ line=$(grep -F 'Http Status:' "$err_file" 2>/dev/null | tail -1 || true)
41
+ if [[ "$line" =~ Http\ Status:\ ([0-9]+) ]]; then
42
+ echo "${BASH_REMATCH[1]}"
43
+ else
44
+ echo "0"
45
+ fi
46
+ }
47
+
48
+ JFROG_PLATFORM_URL="${1:-}"
49
+ SESSION_UUID="${2:-}"
50
+
51
+ if [[ -z "$JFROG_PLATFORM_URL" || -z "$SESSION_UUID" ]]; then
52
+ echo "Usage: bash $0 <platform-url> <session-uuid>" >&2
53
+ exit 1
54
+ fi
55
+
56
+ JFROG_PLATFORM_URL="${JFROG_PLATFORM_URL%/}"
57
+
58
+ for cmd in jq jf; do
59
+ if ! command -v "$cmd" &>/dev/null; then
60
+ echo "ERROR: ${cmd} is not installed" >&2
61
+ exit 1
62
+ fi
63
+ done
64
+
65
+ # Derive server ID from URL
66
+ # SaaS: https://mycompany.jfrog.io → mycompany
67
+ # Self-hosted: https://artifactory.internal.corp → artifactory-internal-corp
68
+ JFROG_HOST=$(echo "$JFROG_PLATFORM_URL" | \
69
+ sed 's|^[a-z]*://||' | sed 's|\.jfrog\.io.*||' | sed 's|[./]|-|g')
70
+
71
+ # Retrieve the one-time token (stdout = JSON body; stderr = jf status lines)
72
+ RESP_FILE="/tmp/jf-login-resp-$$.json"
73
+ STDERR_FILE="/tmp/jf-login-err-$$.txt"
74
+ trap 'rm -f "$RESP_FILE" "$STDERR_FILE"' EXIT
75
+
76
+ : >"$STDERR_FILE"
77
+ set +e
78
+ jf api "/access/api/v2/authentication/jfrog_client_login/token/${SESSION_UUID}" \
79
+ --url "$JFROG_PLATFORM_URL" \
80
+ >"$RESP_FILE" 2>"$STDERR_FILE"
81
+ api_exit=$?
82
+ set -e
83
+
84
+ HTTP_CODE=$(jf_api_http_status "$STDERR_FILE")
85
+ if [[ "$HTTP_CODE" == "0" ]]; then
86
+ HTTP_CODE=$(jf_api_http_status "$RESP_FILE")
87
+ fi
88
+
89
+ if (( api_exit != 0 )); then
90
+ echo "ERROR: Token retrieval failed (HTTP ${HTTP_CODE}, exit ${api_exit})." >&2
91
+ if [[ "$HTTP_CODE" == "400" ]]; then
92
+ echo "The user may not have completed the browser login yet." >&2
93
+ fi
94
+ exit 2
95
+ fi
96
+
97
+ ACCESS_TOKEN=$(grep -v '\[Info\]' "$RESP_FILE" | jq -r '.access_token // empty')
98
+
99
+ if [[ -z "$ACCESS_TOKEN" ]]; then
100
+ echo "ERROR: Response contained no access token. Login must restart from step 1." >&2
101
+ exit 3
102
+ fi
103
+
104
+ # Save credentials to jf config (writes to ~/.jfrog/, needs unrestricted filesystem)
105
+ jf config remove "$JFROG_HOST" --quiet 2>/dev/null || true
106
+
107
+ if ! jf config add "$JFROG_HOST" \
108
+ --url="$JFROG_PLATFORM_URL" \
109
+ --access-token="$ACCESS_TOKEN" \
110
+ --interactive=false 2>/dev/null; then
111
+ echo "ERROR: Failed to save credentials with jf config add." >&2
112
+ echo "This may be caused by sandbox restrictions on ~/.jfrog/ writes." >&2
113
+ exit 4
114
+ fi
115
+
116
+ echo "SERVER_ID=${JFROG_HOST}"
117
+
118
+ echo "--- Verifying authentication ---"
119
+ if ! jf api "/artifactory/api/system/version" --server-id="$JFROG_HOST"; then
120
+ echo "ERROR: Authentication verification failed. Token may not have saved correctly." >&2
121
+ exit 4
122
+ fi
123
+
124
+ echo
125
+ echo "NEXT (mandatory): ask the user whether to make '${JFROG_HOST}' the default jf server."
126
+ echo " - If yes: run 'jf config use ${JFROG_HOST}'"
127
+ echo " - If no: pass '--server-id=${JFROG_HOST}' on every subsequent jf call"
128
+ echo "Do not start any other JFrog operation against this server until this question is asked and answered."