Dumb questions part 4635a. How do you identify the...
# adobe
d
Dumb questions part 4635a. How do you identify the packages needed by a big existing app, other than by testing * everything * and seeing what's broken?
p
Extremely broad/vague question. What is your direct situation related to a coldbox app or ? And what do you refer to as a "package"?
d
@Patrick This isn't a ColdBox question, it's in the #adobe channel. I'm setting up some new CF 2021 servers, which will be used for a large longstanding app. I'm thinking I want to install only the ColdFusion packages we need or expect to need in the near-ish future -- less to maintain, smaller attack and potential defect surface How do identify what those are?
r
The best answer would be some version of "based on knowledge of what the application does and how it does it"; absent that it's probably guess and/or trial-and-error.
a
"run your tests" (which you obviously have, right? Right?) The ones that fail are because missing package.
d
So there's no official (or well-respected unofficial) tool that tries to detect what packages are needed?
a
Then write a test explicit testing the required packages. Then add those packages.
How is anything going to know without running your code to see what you're using?
Which is what yer tests are for: testing regressions.
d
@Adam Cameron Of course! I'll run our test! Why didn't I think of that? Oh right. Because this is a big app built over a many years by lots of people, and there aren't any. Well, there are some, but nothing like full coverage. Believe me, I wish that wasn't so, but in the meantime, I need to set up some new servers :)
r
If I'm standing up an app on a server I am responsible for, it seems like I really should have a more-than-basic understanding of what it does and how it does it (at least from a security standpoint?) and from that be able to make informed decisions about packages which are "obviously" not needed. A matrix of package to tag/function/capability would be very useful but I've not seen one.
šŸ‘ 1
a
Right so I think @Dave Merrill yer SOOL. Just install the whole lot on the new server. Then do a survey of yer code. Write those second lot of tests I mentioned, then lab test removing a package. Rinse/repeat
p
Well I would assume you are setting up a testing environment before a production environment and can confirm what packages are necessary. No I dont believe of a tool that is just going to "detect" a missing package other than fusion reactor and analyzing error logs. And yes most legacy or CF developers in general skip the TEST scripts aspect of development....should be a forced requirement and go back and write for existing too.
a
And going fwd.. chalk this up to "we don't get to have the nice things unless we test our app", and poss adjust yer testing policy accordingly..?
d
The Adobe code analyzer doesn't run your code to analyze its syntax. In an ideal world, there would be something like that in this domain. In regard to the more-than-basic-understanding theory, I know a ton about some pieces of it, because I wrote them, lots about some others, because I've worked on them, some about some others because I've seen parts of some of that code, and very little about other bits. There's a lot of bits. That's just a fact of life, coming into a large existing app. I could seat of the pants guess on that basis, and I will if I gotta, was just wondering if that was the state of the art, absent the full test suite we haven't got. Seems like it is.
s
https://helpx.adobe.com/coldfusion/using/coldfusion-package-manager.html scroll down to the "Code Scanner" section... seems like it will scan your code and tell you what package dependencies you have
šŸ‘ 2
(I have never tried that, but it is in the docs so it must work šŸ˜› )
a
> "a big app built over a many years by lots of people, and there aren't any" > Not having a go at you at all when I say this, @Dave Merrill, as this is endemic in the CFML community. This might've been OK 15yrs ago, but it completely isn't ok since then. How did none of these ppl make the case "fuck we can't be working like this, Team", and sort it out? It's bewildering.
šŸ’„ 1
šŸ˜… 1
ā¤ļø 1
s
Just throwing it out there, but it is not unique to the CFML community. I have seen it with other languages too.
šŸ’Æ 2
a
Def. But I only have a pulpit in this community ;⁠-⁠)
🤣 1
s
@Dave Merrill I'd be interested if that code scanner thing works
I learned a hard lesson on QA in 2015... ever since then I have been a much bigger proponent of a good QA team.
šŸ‘ 1
with automated testing and all that
but before that, I was certainly guilty of the "This is the way we have always done it, and it works fine" mentality
I'm guessing the scanner will give you a list of the packages that you need for the code, but there are probably other ones like the database related packages where you will just need to know what types of databases you connect to.... hopefully you know that, or else Adam is going to yell at you again.
there is also a potential it will be inacurate, if you have old/unused/orphaned code that is the only place you have certain tags that require a particular package... don't tell us that either, because then you might get yelled at for leaving old unused code laying around.
šŸ™‚ 1
t
The code scanner works okay. I used it when 2021 first came out. It missed some really crucial things, but it may have been because I just copied my code on to an empty server, rather than using a working one. In particular, it skipped the scheduled task package (which I realized when I went to configure some and they weren't available), and the sql db driver, which, again, was obvious as soon as I tried to configure a data source.
It was, broadly, the list of packages I expected (and fairly short). And then pulled in others as needed for dependency of those highlevel ones.
s
If only packages were declared in code or a standard configuration file per "application" and could be installed as needed -- like most other JVM-based languages that declare dependencies as part of the application project šŸ™‚
šŸ’Æ 5
🤣 1
s
that sounds hard.. CF is supposed to be easy
šŸ˜„ 1
šŸ˜‚ 1
t
it's one of those things usually handled by the ide... which of course cf doens't really do well either....
s
It sure makes it easy to set up an application on a new machine -- because you don't have to "wonder" what packages are needed: the application specifies them!
s
yeah, you would think the engine itself could figure that out when it compiles the cfml into class files
s
Not IDE. Core to how those languages tend to work. Mostly CLI-based tooling. An IDE may run the commands for you but this is not an IDE thing.
Even JS has this (
package.json
etc).
a
CommandBox / ForgeBox tries to do this, but is a) too *Box-centric (admittedly the fault of the library authors), and b) still a bit immature.
s
And doesn't deal with ACF packages anyway, right?
a
Absolutely not, no. Heaven forbid Adobe collaborate with the biggest and most successful CFML community operation out there. I bet you £50 MarkT is the only person on the CF team who even knows CommandBox exists.
I was speaking to the broader notion of package management
p
Via commandbox you can configure it to add the necessary coldfusion packages on the (box.json scripts) to run via box when spinning up the instance, which is what I do on several of my ACF systems.
But back to your original question Dave, gotta test test test to know what your app needs before you know what cfpm packages you need :)
s
@Adam Cameron > How did none of these ppl make the case "fuck we can't be working like this, Team", and sort it out? You know that that's because it takes TIME to do that, in the short term, that doesn't result in any actual changes to functionality (just promises of future efficiency), so many companies/clients refuse to pay for it.
a
@slcronin šŸ’Æ but... It's our job as professionals to push back and go "sorry, it's just part of the cost of doing the work", or never exposing that detail in the first place! We don't tell them "right I'll need five loops, a coupla conditionals and a DB call"... It's just "code". The stakeholder doesn't care 95% of the time this is an excuse the devs make cos they'd like to cut that particular corner because they are lazy or don't know how to actually do it, and are too misguidedly proud to own that shortcoming
ā˜šŸ» 1
Economising on code quality (which is what dodging testing is) is never a good solution to any perceived constraint. It just isn't.
s
Right; I'm not talking about as you're writing new code, I'm talking about this situation, where it's a huge codebase that's been added to for years and years; getting someone to pay for the time to step back and refactor really can be extremely difficult.
a
Easy. Next bit of code on writes: write a test. Next bit: write another test. I have never worked on a greenfields project. I have learned what I know about testing by dealing with testing existing projects, both new code and backfilling. It just takes willingness.
šŸ‘šŸ» 1
m
Adam, I think you owe someone 50 British smackeroonies. There's at least one other person on the team that knows. šŸ˜›
d
I've forwarded this thread to my team šŸ™‚ Fact remains, I need to set up, configure, and lock down these two new servers, and if you think I'm going to write tests for this whole giant app first, you're not right. I believe in this company (a non-profit that does good work). We do the best we can figure out, starting from where we are, because that's the only place you can ever start. I appreciate the righteous arguments for better practices, and we really do try to make life better as we go, but we also need to keep moving forward, imperfect as the result may be.
šŸ‘ 1
šŸ‘šŸ» 1
a
#proofOfLifeRequired
Hit me up via DM we can work on this
s
@Dave Merrill When you figure out the list of require packages (via the Code Analyzer or whatever), you could probably write a single test that notionally exercised one tag from each package -- so it would fail if any of them were missing -- and then use that as a sanity test on any new servers you stand up. And just ensure there's "policy" that if anyone ever adds code that depends on some new package getting installed, they need to update that one test as well.
šŸ‘ 1
a
^^^ this is the second tranche of tests I mentioned.
Don't sit down for "no tests". That's wrong. Objectively. Start testing
a
@Dave Merrill I think you can literally do a test that will compile each CFC in your app and it'll fail where the CF package isn't installed (so won't compile) - worth a try at least. Something like....
metadataTest.cfc.cfm
šŸ‘ 3
To add to the debate regarding unit tests for decade old apps - I've been in that scenario twice when joining a company. Both companies now have test suites with 1,000s of tests. Sure - it's nowhere near full coverage but it's one hell of a lot better than no coverage. It's largely about mentality. Backfilling tests is hard (as code not written using TDD is often hard to test), but there is no reason not to add tests for every new method you write - that is where you start. Then you start adding tests when you change an existing method etc. The most important thing is simply to start writing tests as routine rather than thinking "we've never had tests before so why start now?" It quickly becomes habit, doesn't make you any slower (once you start thinking with TDD mindset) and the benefits are clearly proven.
šŸ‘ 3
šŸ‘šŸ» 1
a
^^^ this. Plus it also encourages one to write better, tidier, more focused, more modular code, more testable code. Great both for now and for our future selves.
šŸ’Æ 4
d
Hey @Dave Merrill, Scott was correct. I ran into this very thing a month ago when I took over a large legacy project. It was actually pretty simple. 1. I used CFPM's "*scan*" to check the codebase. It produced a list of packages which I kept for future reference. 2. Then, I installed the packages via "*install*" and that comma separated list. The project fired up right away. It all worked very well for me. Well, TBH, everything but the charting which was a bit messed up because they changed the charting engine between the versions. Other than that, smooth sailing.
d
Thanks @David Belanger.
@David Belanger What CF versions were you coming from and going to?
d
I did it twice - the big one was from CF11 to CF2021 and then a smaller one from CF9 to CF2023 (yikes)
As crazy as it sounds, there were no problems in the CF9 upgrade. And it was all tag based code.
CF11 was a bit tricker with the reports (that I mentioned) and the cfdocument PDF printing didn't look quite the same but the client didn't mind the difference in the PDFs...
m
I love to hear that David. I get tons of people asking "are we going to have to rewrite our CF9 code to go to 23 or 21?" And after I recover from fainting at the thoughts of running CF9 in production in 2023 lol, I really only have 2018 examples (which I did personally) to give them. So this is good info. šŸ™‚
d
To be honest, CF9 didn't have a lot of the extras that came in later versions. It was more "bare bones"
j
@David Belanger - quick question: were you able to use scan on a path outside of the cfusion2021\cfusion\wwwroot or was your code in that dir?
d
The code had to be accesible as it normally is via IIS.
So we really didn't have to change much
j
Hmm I'd love to see the command you executed. I've got a dev local site set up in IIS pointing to c:\inetpub\<dir> but for the life of me I could never figure out how to get scan to run against it.
d
I had that problem too - if I remember correctly we did something with forward slashes for the directory structure. Plus, we were on drive D
scan /d/projects/fancyapp <http://localhost:8500>
j
well, knowing it can be done gives me new hope to try some more.
d
I'm guessing it's like the jvm.config issue where you need to us double \\ if you use the Windows file notation
D:\\projects\\fancyapp
d
@Mark Takata (Adobe) It's not what you want to hear I'm sure, but in 2020 we went from cf9 to 2018, and we did have a bunch of stuff to do. Big code base, including a lot of Old Code. But by and large, once we did the work we were ok. Did another big old app in 2021, from cf9 to 2021, same.
d
When it comes to upgrades, sometimes I enjoy code written by a five tagger šŸ‘
šŸ™‚ 1
t
@Dave Merrill 2018 was the one that bit us too. They started throwing errors when you used invalid cfsqltypes which we apparently were doing all over the place --
cf_sql_int
and
cf_sql_string
were the 2 main culprits.
m
@Dave Merrill no I mean I want to hear it all. My ultimate goal is to make upgrades seamless and painless, to the point where you could literally just select a dropdown in admin and it upgrades and you don't have to worry (but you get all the benefits and features of the new version).
d
@Tim Yup. Complicated in our case by generic code that coupled cfsqltype values to form validation. We had some "custom" cfsqltypes that were really validation types, and back when they did that, cfqueryparam didn't complain. I wrote a method to transform the validation version of that kind of struct to a cfqueryparam-compatible version. Ah, memories... @Mark Takata (Adobe) That kind of version interoperability is what I keep hearing about cf 2018 to 2021. Hope it's true, should know soon.
m
These are goals, and they're non-trivial. Still, high on my list. I've only been here a little while too haha, 2018-2021 is pre-mark days. 2023-2024 is really the first version move where I feel I have both been deeply involved but also enabled and empowered. So, I guess, no pressure. LOL.
d
@aliaspooryorik Any thoughts on how to apply a similar compileabity check strategy to cfms as well as cfcs? Neither getMetadata() nor getComponentMetadata() are happy doing that for cfms. I could use the .bat compile tool via exec, but ugh, would much rather keep it in cf (or java I can call from cf).
a
TBH the compile tool is exactly the tool for the job here. It's what it's designed to do, and the code calling it will be obvious in what it's setting out to achieve. You could always take a look at what it's doing... and port that to CFML. It's just a batch file... It's not gonna be breaking the enigma code or anything else terribly complicated.
But I would think "NIH" a bit of you did that. Just
cfexecute
it.
šŸ‘ 1
a
@Dave Merrill hmm, interesting problem.... As Adam says the compile tool is ultimately what would find the issues so that would do it. In terms of doing it with just Testbox then the only thing I can think of which may work is to create a 'wrapper' CFC and then inject the CFM template name and instantiate it. So something like this (off the top of my head)...
Copy code
component {
  function init( template ) {
    include "#template#";
  }
}
a
All this does presuppose that the lack of an installable module will cause a catchable compile-time reception just by virtue of there being some usage of said module anywhere in the file. I'd test that hypothesis before going too far down this route.
a
I tested it and it does indeed choke when the module isn't installed (with CFCs at least dunno about with an include)
⭐ 1
a
What was the code it choked on? A not-installed CFML tag? And was the code executed by being included, or just anywhere in the file? IE: what if the code was within a
<cfif false>
block?
a
So, yeah - bit more testing and the code does need to be exercised for some tags. cfreport seems to blow up immediately, cfftp needs to actually be called.
a
Is the FTP feature that's installable just one facet of FTPness? ie: the baseline
<cfftp>
still "works", but there's a plugin for [some additional FTP gubbinses]?
cfcompile won't help either in that case.
If it's a runtime thing
So.... back to needing tests.
a
seems that way yeah
Apparently tests are useful šŸ˜„ Although you can't really unit test FTP so that's a right pain
a
Copy code
// test.integration.external.FtpTest

it("can connect to [SUPPLIER]'s production FTP server", () => {
    ftp
        name = "ftp_connection",
        result = "local.ftp_connection",
        action = "open",
        secure = true,
        attributeCollection = ProductionFtpServerDetails::SUPPLIER
    ;

    expect(local.ftp_connection.succeeded).toBeTrue()

    ftp name="ftp_connection", action="close";
})
And I'm not making it up. That's copy/pasted/redacted from our codebase
a
yeah, I was thinking of testing in isolation - so no need to have an actual ftp server. I'm probably wrong but I think of that as an integration test.
a
(incl our
shite_coding_standand_for_variable_names
)
// test.integration.external.FtpTest
šŸ‘ 1
Tested with a unit test framework. But not all tests run by a unit test framework are unit tests.
a
You have a coding standard! That's pretty fancy stuff. We have coding standards which vary based on day / dev / file being worked on / what we had for lunch
😲 1
a
All the stuff specific to this question would be integration tests.
a
True dat ^ A good point
a
Progamming in a Team 101, that is.
a
Actually we're not that bad these days, but in the past... wild west šŸ™‚
šŸ‘ 1
a
But yeah... I tend to use "unit test" in the context of "code-oriented automated tests", which is unhelpful @ times
d
I somewhat asked this before, but I'm not sure it got fully answered. What do you test-y folks do about testing the UI? For instance... • Do the variable/column names referenced match what's actually returned by the model method that got called? • Are all reference variables actually defined by something that got called, and caused it to exist in the expected scope? • Do all referenced session vars exist? Do you check the generated HTML against some hard coded expectation? Selenium etc? Also, somewhat a separate question that probably has to be Selenium, but are all in-page interactions, like show-hide behaviors etc correct in all cases?
a
I use Cypress for UI testing - but plan to move to Playwright
āœ… 1
So we have a bunch of "CF" tests and a bunch of "React" tests and then some Cypress tests - currently Cypress tests are run manually against a known database so is testing to full system.
The Cypress tests run through a known scenario (so several pages and form filling etc)
a
Cypress will compare what's rendered with a pre-canned image file of expectations, and report back on visual deltas. No need for mark-up to come into it. But, yes... we (or: our QA team) uses Cypress for end to end / front end tests.
c
Jumping in very late, but on the original topic of "what packages do I need" - once you identify the packages (using the code scanner, tests, or other), you can then export the list from CFAdmin and use the list file to install the same packages on other servers. Although, IIRC, you have to drop down to the CLI to install the packages from the list.
e
Dealing with very legacy Coldfusion code daily and all the while trying to make the code compliant with various EoE laws, SeeFusion, FusionReactor, and logs are going to be your friends. On Windows or Linux, you can set up logging for every process that hits a file to log the file access. You will want to make sure your logging mechanism is on a separate volume, as it can lead to recursion and full administrative rights , Windows, its Auditing / File auditing and can be done on a file and folder basis. You can also use process monitor from sysinternals and power shell, on linux you have the auditd service demon, https://www.redhat.com/sysadmin/configure-linux-auditing-auditd