@mikarinneoracle/oci-cdk-code-only-preview 0.0.28 → 0.0.30
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.
- package/README.md +5 -5
- package/bin/deploy-code-only.js +37 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -57,7 +57,7 @@ Only **`OCI_COMPARTMENT_ID`** (or `OCI_COMPARTMENT_OCID`) is required for deploy
|
|
|
57
57
|
| `OCI_IMAGE_TAG` | Image tag for OCIR | func.yaml version or `latest` |
|
|
58
58
|
| `OCI_CODE_ONLY` | When `1`, use the Code-only Functions ZIP deploy path | `0` |
|
|
59
59
|
| `OCI_CODE_ONLY_SOURCE_DIR` | Source directory to archive for code-only deploy | current directory |
|
|
60
|
-
| `OCI_CODE_ONLY_RUNTIME_NAME` |
|
|
60
|
+
| `OCI_CODE_ONLY_RUNTIME_NAME` | Optional explicit OCI Functions runtime name for code-only deploy (for example `python312.ol9`). OCDK resolves Python automatically from `func.yaml`. | — |
|
|
61
61
|
| **API Gateway** | | |
|
|
62
62
|
| `OCI_APIGATEWAY_DEPLOYMENT_JSON` | Path to deployment spec JSON | `oci_apigateway_deployment.json` in project root |
|
|
63
63
|
| **Stack / networking** | | |
|
|
@@ -115,8 +115,8 @@ export OCI_CLI_PATH="/Users/MRINNE/projects/ocdk/.tools/oci-preview-bin/oci"
|
|
|
115
115
|
# Required: OCI target
|
|
116
116
|
export OCI_COMPARTMENT_ID='ocid1.compartment.oc1...'
|
|
117
117
|
|
|
118
|
-
# Required:
|
|
119
|
-
export OCI_CODE_ONLY_RUNTIME_NAME='python312.ol9'
|
|
118
|
+
# Required: handler. OCDK resolves the latest available Python runtime.
|
|
119
|
+
# Optionally pin one: export OCI_CODE_ONLY_RUNTIME_NAME='python312.ol9'
|
|
120
120
|
export OCI_FUNCTION_HANDLER='func.handler'
|
|
121
121
|
|
|
122
122
|
# Required in func.yaml: name: my-function
|
|
@@ -157,11 +157,11 @@ mvn -DskipTests package
|
|
|
157
157
|
# or: gradle build -x test
|
|
158
158
|
```
|
|
159
159
|
|
|
160
|
-
OCDK also runs this build automatically when no artifact exists yet, and searches the project root, Maven `target/`, and Gradle `build/libs/`. The
|
|
160
|
+
OCDK also runs this build automatically when no artifact exists yet, and searches the project root, Maven `target/`, and Gradle `build/libs/`. The OCI service validates the JAR contents; if several non-source JARs exist, set `OCI_FUNCTION_JAR_PATH` to the one to deploy explicitly. Java archives do not contain the project source tree or a `function/` directory.
|
|
161
161
|
|
|
162
162
|
#### Find the available code-only runtimes
|
|
163
163
|
|
|
164
|
-
The exact `OCI_CODE_ONLY_RUNTIME_NAME` values are enabled per tenancy and region during this Limited Availability preview. Query the Preview CLI
|
|
164
|
+
The exact `OCI_CODE_ONLY_RUNTIME_NAME` values are enabled per tenancy and region during this Limited Availability preview. For Python, OCDK queries this list automatically and selects the newest matching runtime when `func.yaml` contains `runtime: python` (or a versioned value such as `python3.12`). Set `OCI_CODE_ONLY_RUNTIME_NAME` to pin or override that choice. Query the Preview CLI to inspect available runtimes or when deploying another language:
|
|
165
165
|
|
|
166
166
|
```bash
|
|
167
167
|
# List every runtime available to the active OCI profile
|
package/bin/deploy-code-only.js
CHANGED
|
@@ -49,12 +49,45 @@ function integerValue(value, name, fallback) {
|
|
|
49
49
|
return String(parsed);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
function runtimeResourceName(runtime) {
|
|
53
|
+
return runtime.name || runtime['runtime-name'] || runtime.runtimeName || runtime['runtimeName'] || '';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function pythonRuntimeSortKey(runtimeName) {
|
|
57
|
+
const match = runtimeName.toLowerCase().match(/^python(\d+)/);
|
|
58
|
+
return match ? Number.parseInt(match[1], 10) : -1;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function resolvePythonRuntime(runtime) {
|
|
62
|
+
// OCI's preview runtime names omit separators from the Python version:
|
|
63
|
+
// func.yaml's "python3.12" therefore maps to the runtime-list prefix
|
|
64
|
+
// "python312". A plain "python" selects the newest available version.
|
|
65
|
+
const normalizedRuntime = runtime.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
66
|
+
const namePrefix = normalizedRuntime === 'python' ? 'python' : normalizedRuntime;
|
|
67
|
+
const result = jsonOci(['fn', 'runtime', 'list', '--all', '--name-starts-with', namePrefix]);
|
|
68
|
+
const candidates = (result.data || [])
|
|
69
|
+
.map(runtimeResourceName)
|
|
70
|
+
.filter((name) => name.toLowerCase().startsWith(namePrefix));
|
|
71
|
+
if (!candidates.length) {
|
|
72
|
+
fail(`no available code-only runtime matches ${runtime}. Set OCI_CODE_ONLY_RUNTIME_NAME to a runtime returned by "oci fn runtime list --all".`);
|
|
73
|
+
}
|
|
74
|
+
candidates.sort((left, right) => {
|
|
75
|
+
const versionDifference = pythonRuntimeSortKey(right) - pythonRuntimeSortKey(left);
|
|
76
|
+
return versionDifference || right.localeCompare(left);
|
|
77
|
+
});
|
|
78
|
+
const selected = candidates[0];
|
|
79
|
+
console.log(`Selected OCI code-only runtime ${selected} for func.yaml runtime ${runtime}. Set OCI_CODE_ONLY_RUNTIME_NAME to pin a different runtime.`);
|
|
80
|
+
return selected;
|
|
81
|
+
}
|
|
82
|
+
|
|
52
83
|
function readFunctionMetadata() {
|
|
53
84
|
const funcYamlPath = path.join(projectDir, 'func.yaml');
|
|
54
85
|
const yaml = fs.existsSync(funcYamlPath) ? fs.readFileSync(funcYamlPath, 'utf8') : '';
|
|
55
86
|
const functionName = (process.env.OCI_FUNCTION_NAME || yamlValue(yaml, 'name')).trim();
|
|
56
87
|
const appName = (process.env.OCI_FUNCTION_APP_NAME || functionName).trim();
|
|
57
|
-
const
|
|
88
|
+
const configuredRuntime = yamlValue(yaml, 'runtime');
|
|
89
|
+
const runtimeName = (process.env.OCI_CODE_ONLY_RUNTIME_NAME || '').trim()
|
|
90
|
+
|| (configuredRuntime.toLowerCase().startsWith('python') ? resolvePythonRuntime(configuredRuntime) : '');
|
|
58
91
|
const configuredHandler = (process.env.OCI_FUNCTION_HANDLER || yamlValue(yaml, 'cmd') || yamlValue(yaml, 'entrypoint')).trim();
|
|
59
92
|
// The managed Node runtime already invokes `node`; its handler is the script
|
|
60
93
|
// path, whereas a conventional func.yaml entrypoint is `node func.js`.
|
|
@@ -66,7 +99,7 @@ function readFunctionMetadata() {
|
|
|
66
99
|
|
|
67
100
|
if (!functionName) fail('set OCI_FUNCTION_NAME or add name: to func.yaml.');
|
|
68
101
|
if (!appName) fail('set OCI_FUNCTION_APP_NAME.');
|
|
69
|
-
if (!runtimeName) fail('set OCI_CODE_ONLY_RUNTIME_NAME (for example python312.ol9).');
|
|
102
|
+
if (!runtimeName) fail('set OCI_CODE_ONLY_RUNTIME_NAME (for example python312.ol9). Automatic runtime resolution currently supports Python functions with runtime: python in func.yaml.');
|
|
70
103
|
if (!handler) fail('set OCI_FUNCTION_HANDLER or add cmd: to func.yaml.');
|
|
71
104
|
|
|
72
105
|
return { functionName, appName, handler, runtimeName, memory, timeout };
|
|
@@ -123,12 +156,6 @@ function buildJavaProject() {
|
|
|
123
156
|
}
|
|
124
157
|
}
|
|
125
158
|
|
|
126
|
-
function isFatJavaJar(jarPath) {
|
|
127
|
-
const result = spawnSync('jar', ['tf', jarPath], { encoding: 'utf8', shell: false });
|
|
128
|
-
if (result.error || result.status !== 0) return false;
|
|
129
|
-
return /(^|\n)com\/fnproject\/fn\/(api|runtime)\//.test(result.stdout || '');
|
|
130
|
-
}
|
|
131
|
-
|
|
132
159
|
function resolveJavaJar() {
|
|
133
160
|
const configuredPath = (process.env.OCI_CODE_ONLY_JAR_PATH || process.env.OCI_FUNCTION_JAR_PATH || '').trim();
|
|
134
161
|
if (configuredPath) {
|
|
@@ -136,9 +163,6 @@ function resolveJavaJar() {
|
|
|
136
163
|
if (!fs.existsSync(jarPath) || !fs.statSync(jarPath).isFile() || !jarPath.endsWith('.jar')) {
|
|
137
164
|
fail(`OCI_FUNCTION_JAR_PATH must point to an existing .jar file: ${jarPath}`);
|
|
138
165
|
}
|
|
139
|
-
if (!isFatJavaJar(jarPath)) {
|
|
140
|
-
fail(`Java archive is not a fat/uber JAR: ${jarPath}. Configure your Maven Shade or Gradle Shadow build, then point OCI_FUNCTION_JAR_PATH to its output.`);
|
|
141
|
-
}
|
|
142
166
|
return jarPath;
|
|
143
167
|
}
|
|
144
168
|
let candidates = listJavaJarCandidates();
|
|
@@ -148,14 +172,11 @@ function resolveJavaJar() {
|
|
|
148
172
|
}
|
|
149
173
|
const uniqueCandidates = [...new Set(candidates)];
|
|
150
174
|
if (uniqueCandidates.length === 1) {
|
|
151
|
-
if (!isFatJavaJar(uniqueCandidates[0])) {
|
|
152
|
-
fail(`Java build produced a non-fat JAR: ${uniqueCandidates[0]}. Configure your Maven Shade or Gradle Shadow build, then set OCI_FUNCTION_JAR_PATH to its fat/uber JAR.`);
|
|
153
|
-
}
|
|
154
175
|
return uniqueCandidates[0];
|
|
155
176
|
}
|
|
156
177
|
const found = uniqueCandidates.length ? ` Found: ${uniqueCandidates.join(', ')}` : '';
|
|
157
|
-
const guidance = ' Run `mvn -DskipTests package` (or `gradle build -x test`) to produce
|
|
158
|
-
fail(`Java code-only deploy requires exactly one
|
|
178
|
+
const guidance = ' Run `mvn -DskipTests package` (or `gradle build -x test`) to produce the function JAR, then set OCI_FUNCTION_JAR_PATH (for example target/my-function.jar).';
|
|
179
|
+
fail(`Java code-only deploy requires exactly one JAR.${guidance}${found}`);
|
|
159
180
|
}
|
|
160
181
|
|
|
161
182
|
function createArchive(functionName, runtimeName) {
|