Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Packaging): Consider absolute artifact paths (#8325) #8315

Merged
merged 6 commits into from
Jan 7, 2021

Conversation

rib
Copy link
Contributor

@rib rib commented Oct 1, 2020

Closes: #8325
Addresses #6752

Would also close softprops/serverless-rust#82

Although it looks like there may be more than one trigger for issue #6752, this change addresses one case seen as a result of the serverless-rust plugin setting artifacts with an absolute path which wasn't considered by lib/packageService.js.

An alternative fix might change serverless-rust to set a relative path, but this seems like a more general fix.

@codecov-commenter
Copy link

codecov-commenter commented Oct 1, 2020

Codecov Report

Merging #8315 (0b1992e) into master (cf7b25e) will increase coverage by 0.13%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #8315      +/-   ##
==========================================
+ Coverage   87.29%   87.42%   +0.13%     
==========================================
  Files         256      254       -2     
  Lines        9655     9615      -40     
==========================================
- Hits         8428     8406      -22     
+ Misses       1227     1209      -18     
Impacted Files Coverage Δ
lib/plugins/package/lib/packageService.js 96.42% <100.00%> (+5.35%) ⬆️
.../classes/ConfigSchemaHandler/normalizeAjvErrors.js 95.72% <0.00%> (-0.08%) ⬇️
lib/plugins/aws/lib/cloudformationSchema.js
...classes/ConfigSchemaHandler/resolveDataPathSize.js
lib/classes/ConfigSchemaHandler/index.js 91.41% <0.00%> (+0.05%) ⬆️
lib/classes/PluginManager.js 97.29% <0.00%> (+0.67%) ⬆️
lib/plugins/aws/invoke.js 98.21% <0.00%> (+1.78%) ⬆️
lib/plugins/aws/deployFunction.js 95.00% <0.00%> (+5.83%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update cf7b25e...0b1992e. Read the comment docs.

@rib
Copy link
Contributor Author

rib commented Oct 1, 2020

I spent a bunch of time trying to figure out how to run the prettier check but first it wasn't running after installing via npm as described at https://prettier.io/docs/en/install.html and then I hit various config file issues ¯_(ツ)_/¯ so gonna give up with that, sorry.

The change is trivial, and I'm not at all opinionated about it, so hopefully if it looks like a helpful fix someone will be able to handle whatever formatting tweaks are necessary, or rewrite, or find a different approach etc.

Copy link
Contributor

@medikoo medikoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rib thanks for this PR, still this doesn't look related to #6752 (which looks as a result of issue in plugin which blindly assumes existence of function[].package)

While softprops/serverless-rust#82 seems also an error in plugin which for some reason assigns absolute and not relative path to package.artifact

Framework intentionally expects a relative path, as relying on absolute paths doesn't make service portable.

@rib
Copy link
Contributor Author

rib commented Oct 1, 2020

:-( Please at least check the last comment I wrote for #6752 which explains in detail how I arrived at this change last night. Saying thanks "this doesn't look related to #6752" is kinda frustrating from the pov of someone that spent their evening debugging why I've not been able to deploy single functions for a while now (which is what that issue is about). The patch literally fixes the issue for me. It also feels like your bouncing back my own debugging work at me by telling me the cause of softprops/serverless-rust#82 which I posted yesterday and also suggested that it could be good for serverless-rust to set a relative path.

I marked this as Addresses #6752 not Closes because I see that there are clearly multiple things causing the same issue (I wouldn't have known that before spending the time to debug and investigate exactly what the cause of the bug was)

My initial impression was that it might be more robust to remove the assumption about relative paths considering that I didnt see any documentation that explicitly clarified that requirement and it seemed plausible that the exact same issue might just crop up again later if it was only addressed by changing the serverless-rust plugin.

Sorry if I sound grumpy - I think I was caught off guard by how dismissive the last comment was.

It sounds fine to me if serverless only wants to support relative artifact paths and change serverless-rust accordingly (service portability sounds like a good reason). Personally I think if you decide that then I think it might still be worth considering adding a check for absolute paths that at least shows a warning/error to avoid having this issue easily repeat itself in the future.

@medikoo
Copy link
Contributor

medikoo commented Oct 1, 2020

:-( Please at least check the last comment I wrote for #6752 which explains in detail how I arrived at this change last night.

@rib I've read it, and what you've experienced does not look related to original #6752 report, and I've explained why I think so.

The patch literally fixes the issue for me.

I believe that issues should be fixed at the source, and not in whatever way that makes issue "gone" for given specific case.

Here seems the problem is in a plugin which without a valid reason produces an absolute path (note it may trigger some other issues which we're not aware of)

Personally I think if you decide that then I think it might still be worth considering adding a check for absolute paths that at least shows a warning/error to avoid having this issue easily repeat itself in the future.

That's a very good idea. We probably should add such validation inline, directly in logic, as my guess is that plugin sets this property dynamically at runtime, so validating that just by property schema will not work (?)

@rib
Copy link
Contributor Author

rib commented Oct 1, 2020

I've filed #8325 to track the more specific issue I ended up hitting

Copy link
Contributor

@medikoo medikoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it's hard to find a good reason for absolute paths, after all there's no harm in supporting them, and current behavior where invalid path is produced is clearly wrong.

I've proposed on how to solve it more cleanly

packageFunction(functionName) {
const functionObject = this.serverless.service.getFunction(functionName);
const funcPackageConfig = functionObject.package || {};

// use the artifact in function config if provided
if (funcPackageConfig.artifact) {
const filePath = path.join(this.serverless.config.servicePath, funcPackageConfig.artifact);
const filePath = this.absoluteArtifactPath(funcPackageConfig.artifact);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let' simply just use path.resolve instead of path.join (that alone will ensure that absolute paths are respected)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, yep this looks good to me. I don't work with node.js often and was initially surprised that path.join didn't work that way by default - more like python's path.join which would have discarded the first absolute path automatically.

@rib rib force-pushed the wip/rib/single-func-deploy-6752 branch from ef758d1 to 904c2c1 Compare October 2, 2020 16:16
@rib rib changed the title fix(packaging): Consider absolute artifact paths (#6752) fix(packaging): Consider absolute artifact paths (#8325) Oct 2, 2020
@rib
Copy link
Contributor Author

rib commented Oct 2, 2020

Ah, so path.resolve does a bit more than just handle combinations of absolute paths, it will finally combine with the current working directory if the combination still isn't an absolute path and so using path.resolve sort of takes it to an extreme where artifact paths will now always be absolute paths. This requires some unit test updates too - maybe that's ok, or we could potentially go back to the previous version which was a bit more conservative and passed the current unit tests?

@medikoo
Copy link
Contributor

medikoo commented Oct 5, 2020

@rib Tests fail cause of issue in tests, and not that we've introduced a bug. They implied a non absolute servicePath, which I believe, in real world is never the case.

So best way to follow would be to just update tests to mock servicePath with absolute path (we can simply prefix them with /).

As a side note, we configure all new tests with help of runServerless, util, to avoid side effects like that one.

@medikoo
Copy link
Contributor

medikoo commented Oct 29, 2020

@rib what is the status of that? Do you think you can finish it? We'd love to have that in

@medikoo medikoo assigned pgrzesik and unassigned rib Dec 16, 2020
@pgrzesik
Copy link
Contributor

Hello @rib , thanks a lot for your contributions to this PR 🙇 We'd like to wrap it up in the coming days, so I hope you don't mind me taking over your work and applying the finishing changes. Please let me know if you'd still like to continue your work here. Once again, your help is much appreciated 🙇

@rib
Copy link
Contributor Author

rib commented Dec 20, 2020

Yep, that's no problem @pgrzesik, sorry I haven't had time to follow up on this. thanks!

@pgrzesik pgrzesik force-pushed the wip/rib/single-func-deploy-6752 branch from 904c2c1 to 4e1d587 Compare December 22, 2020 16:41
@pgrzesik pgrzesik force-pushed the wip/rib/single-func-deploy-6752 branch from 6ef14f4 to 212b412 Compare December 30, 2020 11:47
this.serverless.config.servicePath,
this.serverless.service.package.artifact
);
funcPackageConfig.artifact = filePath;
functionObject.package = funcPackageConfig;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is a bit controversial as it's changed only because I needed a way to perform an assertion in tests for service-wide scenario - do you think there's another way of doing it without introducing extra production code?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why exactly do we need it?

Technically in tests we should purely test the outcome, so either inspect generated artifact, or generated CF template

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you suggest to assert on Properties.Code.S3Key on CF function resources instead here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you suggest to assert on Properties.Code.S3Key on CF function resources instead here?

As I think more of it, that will also not work, as we just blindly assign there basename of artifact. So fact that full path is broken won't be exposed.

If I understand correctly we're fixing here issue that happens during deployment, where for upload to S3 we try to reach wrong path.

In light of that probably best test is one that tests against sls deploy and sls deploy function commands and confirms that we attempt to upload expected content to S3.

I think we can construct it by mocking AWS SDK through awsRequestStubMap option, and by setting lastLifecycleHookName to avoid full deployment process.
e.g. we have test that does something similar here:

lastLifecycleHookName: 'aws:deploy:deploy:checkForChanges',

As hint you may inspect what exactly lifecycle events are triggered in which order by running deployment with debug branch (I've just ensured it's up to date with master). It logs all meta about that (we will put into core with regular debug logs after we have #1720 addressed)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For sls deploy function we're just passing artifact data to updateFunctionCode, so I've went this route for these tests (ensuring that AWS API is called with correct content). As for sls deploy, I believe it's not affected by this issue, but I'll try to come up with meaningful tests for that scenario as well

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've adjusted the approach a bit as confirming on the content was a bit cumbersome in case of readStream, so I've decided to confirm that the stream is created based on proper path to artifact

@pgrzesik pgrzesik requested a review from medikoo December 30, 2020 12:01
@pgrzesik pgrzesik force-pushed the wip/rib/single-func-deploy-6752 branch from 212b412 to 88df226 Compare December 30, 2020 16:27
@pgrzesik pgrzesik force-pushed the wip/rib/single-func-deploy-6752 branch from 88df226 to e3bb77c Compare December 30, 2020 16:32
@pgrzesik pgrzesik force-pushed the wip/rib/single-func-deploy-6752 branch from c35f779 to 943b75c Compare January 5, 2021 07:56
@pgrzesik
Copy link
Contributor

pgrzesik commented Jan 5, 2021

@medikoo Would you be able to take a second look whenever you got a chance?

Copy link
Contributor

@medikoo medikoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pgrzesik looks great! I have just few questions, please see my comments

},
},
},
});
});
it('should support `package.artifact`', () => {

it.skip('should support `package.artifact`', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add TODO: prefix to message

});

// One with CF template, one with function artifact and one with provided function artifact
expect(s3UploadStub).to.be.calledThrice;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it's important to confirm on that (?) I guess there are some unrelated uploads involved there

Copy link
Contributor

@pgrzesik pgrzesik Jan 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to differentiate this way between the two cases (for service-wide scenario there's one upload less), but it's not essential I think

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks as implementation detail, which may change without breaking functionality (e.g. in some other unrelated part we'll do S3 upload and it'll break tests here), so i wouldn't cover this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense, removed 👍

Comment on lines 652 to 653
absoluteArtifactFilePath = path.join(process.cwd(), 'newArtifact.zip');
await fs.promises.writeFile(absoluteArtifactFilePath, zipContent);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can reuse artifact directly from a fixture (we may eventually copy it to a new path, assuming that we rely on filename to confirm that things works)

@pgrzesik pgrzesik force-pushed the wip/rib/single-func-deploy-6752 branch from 2a3f6cf to eaf74cf Compare January 7, 2021 07:44
@pgrzesik pgrzesik requested a review from medikoo January 7, 2021 07:52
@pgrzesik pgrzesik force-pushed the wip/rib/single-func-deploy-6752 branch from eaf74cf to 0b1992e Compare January 7, 2021 12:25
Copy link
Contributor

@medikoo medikoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! 👍

@pgrzesik pgrzesik changed the title fix(packaging): Consider absolute artifact paths (#8325) fix(Packaging): Consider absolute artifact paths (#8325) Jan 7, 2021
@pgrzesik pgrzesik merged commit bcbbd47 into serverless:master Jan 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants