feat: Update the sentry release registry with AWS Lambda layer versions#172
Conversation
The AwsLambdaLayer target interaction with the AWS SDK is abstracted, AwsLambdaLayerManager deals with it now. Still work in progress: functionality, docs and tests missing.
tonyo
left a comment
There was a problem hiding this comment.
Left a few minor comments.
General thoughts:
- The registry update now runs unconditionally, wdyt about making it configurable on a target level? Or, do we e.g. plan to release beta layer versions that don't need to be pushed to the registry?
- I'm a bit salty that we now have to blur borders of target responsibilities (basically, running the registry target functions from the aws-lambda target). Not your fault @iker-barriocanal, but more like a reminder that we might want to reconsider the overall design of how targets work together and whether we need, for example, some form of state (local or remote) when publishing.
Also, deleted mocked config file for the GithubGlobalConfig and removed mocked call from the test.
… registry targets
…lease The dry-run mode is on, the AWS target doesn't publish new layers nor push anything to the registry. When dry-run mode is off, the AWS target publishes new layers, but information of these layers is not published to the registry unless otherwise specified in the config file with `linkPrereleases`.
…c/utils/registry`
|
Oh, and please update the changelog |
| @@ -1,5 +1,9 @@ | |||
| # Changelog | |||
|
|
|||
| ## 0.16.2 | |||
There was a problem hiding this comment.
Note: if you don't plan to release a new version immediately after the PR, let's not fill the version right away, but write "Unreleased" in the header. Who knows, maybe the next release will be a major bump
| `Did not publish layers for ${runtime.name}. ` + | ||
| `Something went wrong with AWS: ${error.message}` | ||
| ); | ||
| return; |
| const regionsVersions = publishedLayers.map(layer => { | ||
| return { | ||
| region: layer.region, | ||
| version: layer.version.toString(), | ||
| }; | ||
| }); |
There was a problem hiding this comment.
const regionsVersions = publishedLayers.map(({region, version}) => ({region, version: version.toString()}));| if (!fs.existsSync(baseFilepath)) { | ||
| logger.warn(`The ${runtime.name} base file is missing.`); | ||
| fs.writeFileSync(newVersionFilepath, JSON.stringify(runtimeData)); | ||
| } else { | ||
| const baseData = JSON.parse(fs.readFileSync(baseFilepath).toString()); | ||
| fs.writeFileSync( | ||
| newVersionFilepath, | ||
| JSON.stringify({ ...baseData, ...runtimeData }) | ||
| ); | ||
| } |
There was a problem hiding this comment.
let baseData;
if (fs.existsSync(baseFilePath)) {
baseData = JSON.parse(fs.readFileSync(baseFilepath, {encoding: 'utf-8'}));
} else {
baseData = {};
logger.warn(`The ${runtime.name} base file is missing.`);
}
fs.writeFileSync(
newVersionFilepath,
JSON.stringify({ ...baseData, ...runtimeData }),
);| version: string, | ||
| versionFilepath: string | ||
| ): void { | ||
| const latestVersionPath = path.posix.join(directory, 'latest.json'); |
There was a problem hiding this comment.
'latest.json' should probably be a constant:
const LATEST_VERSION_FILE_NAME='latest.json';| const previousVersion = fs | ||
| .readlinkSync(latestVersionPath) | ||
| .split('.json')[0]; |
There was a problem hiding this comment.
const [previousVersion] = fs.readlinkSync(latestVersionPath).split('.json', 1);May consider using path.parse() or similar path methods too. I checked but didn't find anything that gives you the full path sans the extension but not sure if that's your real intention here. Looks like path.basename(latestVersionPath, '.json') would fit here.
| * @returns Information about the published layer: region, arn and version. | ||
| */ | ||
| public async publishLayerToRegion(region: string): Promise<PublishedLayer> { | ||
| const lambda = new Lambda({ region: region }); |
There was a problem hiding this comment.
const lambda = new Lambda({ region });| DescribeRegionsCommandOutput | ||
| > { | ||
| logger.debug('Fetching AWS regions...'); | ||
| const ec2 = new EC2({ region: 'us-east-2' }); |
There was a problem hiding this comment.
Shouldn't this default region be carried out to a global constant?
| const regionNames: string[] = []; | ||
| awsRegions.Regions?.map(currentRegion => { | ||
| if (currentRegion.RegionName !== undefined) { | ||
| regionNames.push(currentRegion.RegionName); | ||
| } | ||
| }); | ||
| return regionNames; |
There was a problem hiding this comment.
return awsRegions.Regions?.filter(currentRegion => currentRegion.RegionName !== undefined) || [];| * @param arn The ARN of the account. | ||
| */ | ||
| export function getAccountFromArn(arn: string): string { | ||
| return arn.split(ARN_SEPARATOR)[ARN_ACCOUNT_INDEX]; |
There was a problem hiding this comment.
This kind of screams for a more readable RegExp to me.
| * Returns a GithubRemote object to the sentry release registry. | ||
| */ | ||
| export function getRegistryGithubRemote(): GithubRemote { | ||
| return new GithubRemote('getsentry', 'sentry-release-registry'); |
## Summary Resolves **10 open Dependabot alerts** across 5 CVEs and dismisses 2 low-severity esbuild alerts as tolerable risk. ### Alerts Fixed | Alert(s) | Package | Severity | CVE | Fix | |----------|---------|----------|-----|-----| | #180, #181 | `tar` | Medium | GHSA-vmf3-w455-68vh | Bump direct pin `7.5.11` -> `7.5.16` | | #178, #179 | `form-data` | High | GHSA-hmw2-7cc7-3qxx | `pnpm.overrides` for `4.0.6` (v4) and `2.5.6` (v2) | | #172, #176 | `vite` (root) | High + Medium | GHSA-fx2h-pf6j-xcff, GHSA-v6wh-96g9-6wx3 | Add as direct devDep `^7.3.5` + override | | #173, #177 | `vite` (docs) | High + Medium | same | `pnpm.overrides` in docs | | #174, #175 | `astro` | High + Medium | GHSA-2pvr-wf23-7pc7, GHSA-jrpj-wcv7-9fh9 | `pnpm update` -> `6.4.8` | ### Alerts Dismissed (tolerable_risk) | Alert(s) | Package | Severity | Reason | |----------|---------|----------|--------| | #167, #168 | `esbuild` | Low | GHSA-g7r4-m6w7-qqqr - Windows dev-server only vulnerability. Craft is a CLI tool, docs is a static site. Transitive dep of `[email protected]` which pins `esbuild@^0.27.0` - cannot fix without vite 8 major bump. | ## Changes ### Root project (`package.json`) - `tar`: `7.5.11` -> `7.5.16` (direct pin bump) - `vite`: added as devDependency at `^7.3.5` (was only transitive via vitest) - `pnpm.overrides`: added `form-data@>=4: ^4.0.6`, `form-data@<3: ^2.5.6`, `vite: ^7.3.5` ### Docs project (`docs/package.json`) - `astro`: resolved `5.16.11` -> `6.4.8` (specifier `^6.1.10` allowed it) - `@astrojs/starlight`: resolved `0.37.3` -> `0.38.3` - `pnpm.overrides`: added `vite: ^7.3.5` ## Verification - `pnpm build` - passed - `pnpm test` - 1025 passed, 1 skipped - `pnpm lint` - 0 errors - `pnpm docs:build` - 27 pages built successfully
Summary
The latest versions of the AWS Lambda layers will be needed in our docs (manual setup) as well as in Sentry (automated setup). This PR updates the release registry with the information of the latest updated layers, by generating files that describe them during the release process.
Registry updates
The
aws-lambda-layertarget will have a change in.craft.yml, wherecompatibleRuntimeswill be a list of objects containing a name and a list of versions (e.g.name: nodeandversions: ['nodejs10.x', 'nodejs12.x']). The new files will be placed in the directoryaws-lambda-layers/{runtime name}/, and will be named{version to release}.json.Each version file contains both dynamic and static attributes. Dynamic attributes are extracted when layers are created:
canonical. The canonical name of the layer, following the patternaws-layer:{runtime name}.sdk_version. The version to be released.account_number. The account number of the account creating the layers. This can be found in the ARN of the created layer (arn:aws:lambda:{region}:{account number}:layer:{layer name}:{layer version}).layer_name. The name of the layer. This value is taken from the.craft.ymlproject config file.regions. A list of mappings of regions to versions, since different regions may have different versions.Static attributes are common attributes to all the versions and won't usually change. They are located in the
base.jsonfile, placed in each runtime directory. All the attributes in this file will be added to the new version files.name,repo_urlandmain_docs_urlare the only static attributes so far.It's important that the directories already exist in the registry, since no new directories are created (already existing for
nodegetsentry/sentry-release-registry#35). If the directory structure doesn't exist, a warning message will appear; and ARNs will always be logged. Besides, symlinks targeting to the major, minor and latest version will be created.latest.jsonwill always link to the latest created version.PR changes
The main changes in this PR are the new
src/utils/awsLambdaLayerManager, a file containing the interaction of Craft and AWS. All the functionality of this file was previously onsrc/targets/awsLambdaLayer, but a couple of util functions. This abstraction has been made to make the code easier to deal with.The
src/targets/awsLambdaLayer, where the core functionality of theaws-lambda-layertarget is, has now two extra features. On the one hand, the relevant information is collected (static and dynamic attributes), written to a file, and symlinks updated. On the other hand, these new files are created in a cloned repo, and then committed and pushed to the remote.Lastly, the README has been updated, and tests and mocks have been added too.