@salesforce/lds-core-release 1.243.0 → 1.245.0
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 +2 -57
- package/package.json +1 -1
- package/src/release.py +104 -26
package/README.md
CHANGED
|
@@ -1,58 +1,3 @@
|
|
|
1
|
-
# LDS Release
|
|
1
|
+
# LDS Core Release
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
1. make sure you have `python3` on your PATH
|
|
6
|
-
2. make sure you have either run `yarn build:core-artifacts` from the root of the repo to generate the artifacts, or downloaded and unzipped a Github release artifact
|
|
7
|
-
|
|
8
|
-
## How to run locally
|
|
9
|
-
|
|
10
|
-
It's really simple, just run `yarn release:python` from this package, then use the prompts to give the path to your release artifact dir and the path to your core.
|
|
11
|
-
|
|
12
|
-
## Running a release on a Salesforce workspace
|
|
13
|
-
|
|
14
|
-
This part assumes you have a [Salesforce workspace available](https://sfdc.co/ws), and using the **Core on Git** Workspace template. This script does not handle p4 commands.
|
|
15
|
-
|
|
16
|
-
1. `cd` out of the core path to something like `/opt/workspace`. Make a working directory for yourself here. `mkdir lds`, and `cd` into it.. `cd lds`
|
|
17
|
-
2. Authenticate to Github.com via the installed github cli. `gh auth login`. Make sure you're logged into your EMU account. Specify that HTTPS is fine for git operations. You'll have to paste an auth code to login.
|
|
18
|
-
3. Download the release artifact for the version you're trying to release. `gh release download {release version} --repo=salesforce-experience-platform-emu/lds-lightning-platform`
|
|
19
|
-
4. Unzip the release artifact. `unzip sfdc.zip`
|
|
20
|
-
5. Run the release script that is included in the artifact. `python3 output/lds/release.py`
|
|
21
|
-
|
|
22
|
-
- Answer the prompts to point the script to the right directories. To clarify, this is the `sfdc` directory in the unzipped dir.
|
|
23
|
-
|
|
24
|
-
```
|
|
25
|
-
python output/lds/release.py
|
|
26
|
-
Enter the location of the LDS release artifact. Default: ../../output/sfdc: ./output/sfdc
|
|
27
|
-
Enter the core filepath. Default: /Users/scarraway/repositories/salesforce/core/core-public/core: /opt/workspace/core-public/core
|
|
28
|
-
Source filepath: output/sfdc
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
- Validate the changes look correct
|
|
32
|
-
|
|
33
|
-
6. Create a branch with all the changes and submit for review.
|
|
34
|
-
|
|
35
|
-
## Troubleshooting
|
|
36
|
-
|
|
37
|
-
If you see an error with Git LFS when pushing, you may need to force another change to get LFS up to date.
|
|
38
|
-
Example:
|
|
39
|
-
|
|
40
|
-
```
|
|
41
|
-
Spawned process 5149 to upload telemetry. Logs at /opt/workspace/gimlet-home/logs/20230712141414/telemetry-upload.nohup.out
|
|
42
|
-
Your token to access the Git-lfs instance (https://gitlfs.soma.salesforce.com/artifactory/api/lfs/gitlfs-coreapp) is valid.
|
|
43
|
-
Preparing lfs
|
|
44
|
-
Git LFS upload failed: 33% (1/3), 4.6 KB | 0 B/s
|
|
45
|
-
(missing) core/ui-force-components/modules/force/ldsAdaptersUiapi/ldsAdaptersUiapi.js (06dcf9a38c6a94e13f9d687b215f3a55d2243df2e2cf19b4464eac964e2824f2)
|
|
46
|
-
(missing) core/ui-force-components/modules/force/ldsAdaptersAnalyticsWave/ldsAdaptersAnalyticsWave.js (9479f6181b61748b5a1256d9df726746df8982f5486043cb81d0b08408fac0bc)
|
|
47
|
-
hint: Your push was rejected due to missing or corrupt local objects.
|
|
48
|
-
hint: You can disable this check with: `git config lfs.allowincompletepush true`
|
|
49
|
-
Uploading LFS objects: 33% (1/3), 4.6 KB | 0 B/s, done.
|
|
50
|
-
error: failed to push some refs to 'https://gitcore.soma.salesforce.com/core-2206/core-public.git'
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
**CAUTION** Do NOT run `git config lfs.allowincompletepush true`. It can lead to NPE when core-on-git is building your branch.
|
|
54
|
-
|
|
55
|
-
Instead you can
|
|
56
|
-
|
|
57
|
-
1. Make a whitespace change and re-push those files to your branch.
|
|
58
|
-
2. Use `git lfs pull --include ui-force-components/modules/force/ldsAdaptersAnalyticsWave/ldsAdaptersAnalyticsWave.js` for each file complained about above. This forces your local git to pull down the LFS files. Then make a whitespace change and re-push.
|
|
3
|
+
This package defines a portable [python script](./src/release.py) along with assets to successfully update core with the latest lds-lightning-platform assets. It can be used for local development, integration testing, and the LDS weekly release. Usage is documented [here](../../docs/release/core-release-tasks.md)
|
package/package.json
CHANGED
package/src/release.py
CHANGED
|
@@ -1,35 +1,96 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
import
|
|
2
|
+
import subprocess;
|
|
3
|
+
import errno;
|
|
3
4
|
from string import Template
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
from typing import List
|
|
6
7
|
from functools import lru_cache
|
|
8
|
+
import asyncio
|
|
9
|
+
import argparse
|
|
7
10
|
|
|
8
11
|
# resolve static files used by the script
|
|
9
12
|
script_path = Path(__file__).resolve()
|
|
10
13
|
script_directory = script_path.parent
|
|
11
14
|
assets_path = script_directory / 'assets'
|
|
12
15
|
|
|
16
|
+
async def usingPerforce(coreDir):
|
|
17
|
+
isPerforceDir = True
|
|
18
|
+
try:
|
|
19
|
+
# Run the 'p4 where ...' command using subprocess
|
|
20
|
+
result = subprocess.run(['p4 where ...'], cwd=coreDir, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True)
|
|
21
|
+
# Check if the error message indicates the directory is not under client's root
|
|
22
|
+
if "is not under client's root" in result.stderr:
|
|
23
|
+
print('Client root error!')
|
|
24
|
+
isPerforceDir = False
|
|
25
|
+
|
|
26
|
+
except subprocess.CalledProcessError as e:
|
|
27
|
+
print('Got an error trying to verify p4 workspace. Assuming Git.')
|
|
28
|
+
print(e)
|
|
29
|
+
# Handle any errors, but we assume that if 'p4 where' fails, it's not a Perforce directory
|
|
30
|
+
isPerforceDir = False
|
|
31
|
+
|
|
32
|
+
return isPerforceDir
|
|
33
|
+
|
|
34
|
+
async def checkoutFileP4(corePath: Path, coreDir: Path):
|
|
35
|
+
# Check if the file exists
|
|
36
|
+
if not corePath.exists():
|
|
37
|
+
# If it doesn't exist, add it to Perforce
|
|
38
|
+
print('New file in perforce. Attempting add.')
|
|
39
|
+
p4_command = [f'p4 add {corePath}']
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
subprocess.run(p4_command, cwd=coreDir, check=True, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
|
43
|
+
except subprocess.CalledProcessError as e:
|
|
44
|
+
print(f"Error adding file to Perforce: {e}")
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
# Create the directory structure if it doesn't exist
|
|
48
|
+
corePath.parent.mkdir(parents=True, exist_ok=True)
|
|
49
|
+
|
|
50
|
+
# Create an empty file
|
|
51
|
+
try:
|
|
52
|
+
corePath.touch()
|
|
53
|
+
except OSError as e:
|
|
54
|
+
if e.errno == errno.EACCES:
|
|
55
|
+
print(f"File is not writable. Make sure to run 'p4 edit {corePath}'.")
|
|
56
|
+
else:
|
|
57
|
+
print(f"Error creating file: {e}")
|
|
58
|
+
else:
|
|
59
|
+
# If the file exists, edit it in Perforce
|
|
60
|
+
p4_command = [f'p4 edit {corePath}']
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
subprocess.run(p4_command, cwd=coreDir, check=True, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
|
64
|
+
except subprocess.CalledProcessError as e:
|
|
65
|
+
print(f"Error editing file in Perforce: {e}")
|
|
66
|
+
|
|
67
|
+
# Check if the file is writable
|
|
68
|
+
try:
|
|
69
|
+
corePath.touch(mode=0o666, exist_ok=True)
|
|
70
|
+
except OSError as e:
|
|
71
|
+
if e.errno == errno.EACCES:
|
|
72
|
+
print(f"File is not writable. Make sure to run 'p4 edit {corePath}'.")
|
|
73
|
+
else:
|
|
74
|
+
print(f"Error checking file access: {e}")
|
|
75
|
+
|
|
13
76
|
# Python 3 script that does the LDS release.
|
|
14
|
-
def copy_release(source_dir: Path, destination_dir: Path):
|
|
77
|
+
async def copy_release(source_dir: Path, destination_dir: Path, useP4: bool):
|
|
15
78
|
try:
|
|
16
79
|
new_modules = []
|
|
17
80
|
|
|
18
|
-
# Create the destination directory if it doesn't exist
|
|
19
|
-
if not destination_dir.exists():
|
|
20
|
-
destination_dir.mkdir(parents=True)
|
|
21
|
-
|
|
22
81
|
# Copy files from the source directory to the destination directory
|
|
23
82
|
for file in Path(source_dir).rglob("*.js"):
|
|
24
83
|
print(f"File detected: {file}")
|
|
25
84
|
|
|
26
85
|
relative_path = file.relative_to(source_dir)
|
|
27
|
-
print(f"relative path: {relative_path}")
|
|
28
86
|
destination_file = destination_dir / relative_path
|
|
87
|
+
|
|
88
|
+
if(useP4):
|
|
89
|
+
await checkoutFileP4(destination_file, destination_dir)
|
|
90
|
+
|
|
29
91
|
destination_file.parent.mkdir(parents=True, exist_ok=True)
|
|
30
92
|
destination_file.touch(mode= 0o666 ,exist_ok=True)
|
|
31
93
|
|
|
32
|
-
print(f"Trying to copy file: {relative_path}")
|
|
33
94
|
# Copy the file
|
|
34
95
|
destination_file.write_bytes(file.read_bytes())
|
|
35
96
|
# Get the directory name (module name)
|
|
@@ -43,6 +104,8 @@ def copy_release(source_dir: Path, destination_dir: Path):
|
|
|
43
104
|
new_modules.append(module_name)
|
|
44
105
|
# Create the meta xml file if missing
|
|
45
106
|
meta_xml_template_bytes = read_js_meta_template()
|
|
107
|
+
if(useP4):
|
|
108
|
+
await checkoutFileP4(meta_xml_file, destination_dir)
|
|
46
109
|
meta_xml_file.touch(mode= 0o666 ,exist_ok=True)
|
|
47
110
|
meta_xml_file.write_bytes(meta_xml_template_bytes)
|
|
48
111
|
|
|
@@ -85,36 +148,51 @@ def replace_string_in_file(file_path: Path, old_string: str, new_string: str, su
|
|
|
85
148
|
except Exception as e:
|
|
86
149
|
print("An error occurred while replacing the string:", e)
|
|
87
150
|
|
|
88
|
-
def update_ownership_yml(destination_filepath: Path, new_modules: List[str]):
|
|
89
|
-
if(len(new_modules) == 0):
|
|
90
|
-
return
|
|
91
|
-
|
|
151
|
+
async def update_ownership_yml(destination_filepath: Path, new_modules: List[str], useP4: bool):
|
|
92
152
|
ownershipYamlPath = destination_filepath / 'ui-force-components' / 'java' / 'resources' / 'ownership.yaml'
|
|
93
153
|
newEntriesString = "\n".join([f" - modules/force/{module}/**" for module in new_modules]) + "\n - modules/force/ldsBindings/**"
|
|
154
|
+
if useP4:
|
|
155
|
+
await checkoutFileP4(ownershipYamlPath, destination_filepath)
|
|
94
156
|
ownershipYamlPath.chmod(0o666)
|
|
95
157
|
replace_string_in_file(ownershipYamlPath, ' - modules/force/ldsBindings/**', newEntriesString, "Updated ownership.yml")
|
|
96
158
|
return
|
|
97
159
|
|
|
98
|
-
def update_lwc_workflow_test(destination_filepath: Path, new_modules: List[str]):
|
|
99
|
-
if(len(new_modules) == 0):
|
|
100
|
-
return
|
|
101
|
-
|
|
160
|
+
async def update_lwc_workflow_test(destination_filepath: Path, new_modules: List[str], useP4: bool):
|
|
102
161
|
lwcWorkflowTestPath = destination_filepath / 'aura-impl-sfdc' / 'test' / 'func' / 'java' / 'src' / 'aura' / 'impl' / 'sfdc' / 'modules' / 'LWCWorkflowTest.java'
|
|
103
162
|
newEntriesString = "\n".join([f' "force/{module}",' for module in new_modules]) + '\n "force/ldsBindings",'
|
|
163
|
+
if useP4:
|
|
164
|
+
await checkoutFileP4(lwcWorkflowTestPath, destination_filepath)
|
|
165
|
+
|
|
104
166
|
lwcWorkflowTestPath.chmod(0o666)
|
|
105
167
|
replace_string_in_file(lwcWorkflowTestPath, ' "force/ldsBindings",', newEntriesString, "Updated LWCWorkflowTest")
|
|
106
168
|
return
|
|
107
169
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
170
|
+
async def main():
|
|
171
|
+
parser = argparse.ArgumentParser(description="The release script for LDS")
|
|
172
|
+
parser.add_argument("-o", "--outputDir", help="Path to the output directory generated by yarn build:core-artifacts")
|
|
173
|
+
parser.add_argument("-c", "--coreDir", help="Path to the target core directory")
|
|
174
|
+
args = parser.parse_args()
|
|
175
|
+
|
|
176
|
+
source_filepath = Path(args.outputDir or input("Enter the location of the LDS release artifact. Default: ./output: ") or './output').expanduser()
|
|
177
|
+
print("LDS Release artifact path:", source_filepath)
|
|
178
|
+
if not (source_filepath / 'sfdc').exists():
|
|
179
|
+
raise SystemExit(f"LDS release artifact directory({source_filepath}) does not seem to exist. Did you provide the correct path? Did you run yarn build:core-artifacts?")
|
|
180
|
+
destination_filepath = Path(args.coreDir or input("Enter the core filepath. Default: /opt/workspace/core-public/core: ") or '/opt/workspace/core-public/core').expanduser()
|
|
181
|
+
print("Destination filepath:", destination_filepath)
|
|
182
|
+
if not (destination_filepath / 'ui-force-components').exists():
|
|
183
|
+
raise SystemExit(f"Destination core directory does not seem to contain ui-force-components. Did you provide the correct path to your core directory?")
|
|
184
|
+
# Print the entered filepaths
|
|
111
185
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
186
|
+
|
|
187
|
+
useP4 = await usingPerforce(destination_filepath)
|
|
188
|
+
new_modules = await copy_release(source_filepath / 'sfdc', destination_filepath, useP4)
|
|
115
189
|
|
|
116
|
-
new_modules
|
|
190
|
+
if(len(new_modules) == 0):
|
|
191
|
+
print(f"No new modules detected")
|
|
192
|
+
return
|
|
193
|
+
else:
|
|
194
|
+
print(f"New modules added: {new_modules}")
|
|
195
|
+
await update_ownership_yml(destination_filepath, new_modules, useP4)
|
|
196
|
+
await update_lwc_workflow_test(destination_filepath, new_modules, useP4)
|
|
117
197
|
|
|
118
|
-
|
|
119
|
-
update_ownership_yml(destination_filepath, new_modules)
|
|
120
|
-
update_lwc_workflow_test(destination_filepath, new_modules)
|
|
198
|
+
asyncio.run(main())
|