Saturday, 28 August 2021

The certificate associated with the consumer key has expired

This week a couple of my continuous integration builds started failing. This in itself isn't unusual - these are typically end to end builds that create scratch orgs, set up standing data, run a bunch of tests, so it doesn't take much to tip the odd one over.  I didn't find anything helpful about the error message online though, so I'm writing this post so that it will appear as a match for the next person that is trying to find out more!

The error was something I hadn't seen before - "The certificate associated with the consumer key has expired.".  Googling didn't bring up much, one person had reported it before and they had got around it by removing their CLI installation and starting again. Not an option for me as the CLI setup on my CI machine would take a fair amount of effort to recreate. Time to start digging.

The first place I looked was the CLI itself - I typically don't update this much on my CI machine, as it hasn't been the most stable tool in terms of working new releases over the last year or so. It seemed entirely plausible that something embedded in the CLI had expired, so I updated everything and waited. Sadly this didn't fix my scratch builds, but it did break one of my static code analysis jobs, as a rule had switched from Java to XPath, and I had references to the Java class in one of my custom configurations. That was a relatively quick fix, so shortly I was no worse than the day before.

Next was the JWT grant for the org that I'm using as a dev hub for these builds. I was able to query data from the org without any problem, so it didn't seem to be that. Then I tried creating a scratch org and got the same error, so it seemed likely that it was related, but not as obviously as it might have been. 

Once I'd remembered how to access a connected app's configuration, I could see that the self-signed certificate for the app had expired about 9 hours before the build started failing.  Clearly I had found the problem.  

My next thought was that I would have to go through the whole JWT grant again - not something I look forward to, mainly because I don't do it that often and I always remember it being worse than it is. The first thing I needed to do though, was create a new self-signed certificate for the connected app, which I duly did. I was tempted to make the certificate last 10 years (apparently openssl self-signed certs can go out for around 75 years), but that felt like trading security for convenience, which is never a good thing to do. Once I'd updated the cert I decided I'd have a quick go at creating a new scratch org and it worked! No need to generate a new grant, I was off to the races. I then encountered a problem deleting scratch orgs, but this is something I'm also seeing on another machine that is authorised to a different dev hub via web login, so it feels like that is a different issue. I can also work around it with some scheduled Apex, so I'm happy to wait and see if it goes away!




Saturday, 21 August 2021

The Public Nature of Modern Programming

Then

When I got my first programming job, way back in 1987, it was a quite a private and solitary occupation. The Design Authority for my project gave me a detailed design for a procedure, including explicit definitions of the interfaces that I would use to interact with the rest of the system. I would then write the code for the procedure, test it locally and check it into version control. If I didn't need any clarification, I wouldn't speak to anyone as part of this process. I'd chat to my colleagues that I shared an office with, but in terms of doing my work it would be me and a screen. 

My code wouldn't be looked at by anyone else unless there was an issue when the next build took place, which there always was, as there were hundreds of new procedures that had never been slammed together before. The build team would take the first stab at fixing the issues, and if they were successful then I wouldn't know anything about this. If they were unsuccessful we would then enter a period of confusion as they typically wanted help with their fix rather than the underlying problem, and I would wonder where this code they were talking about had come from. 

My working life was spent solving problems that others were probably spending time solving, but it would never have occurred to me to share information about what I was doing, nor would I have had the first clue about how to go about sharing it. 

Outside of work, I would almost never talk to anyone about programming unless I was catching up with someone I'd been at college with, but it would be very superficial and typically about which languages and business areas we were working in, before getting down to the serious business of talking about sport. I'd also rarely do any programming outside of work. I might fiddle around a bit with some Basic, Pascal or 6502 assembler on my BBC Model B, but nothing serious. And certainly nothing that I'd consider telling anyone else about.  Some people wrote games and sent the source into magazines that might print it, but as a professional programmer I already got paid to write code so didn't need this outlet. 

Programming was a job like any other - I went to an office, worked there for a set number of hours a day, then went home and did whatever else I was interested in at the time. Unless you were a close friend or family member, you wouldn't have known that I programmed computers for a living, and unless you were a programmer yourself, it was hard for me to communicate exactly what I did every day.

The stereotype of a programmer was someone sitting in a darkened basement, being fed written requirements, and spending their days staring at a screen and typing. Which was pretty accurate.

Now

Programming in 2021 has changed beyond all recognition. It's now a collaborative and very public occupation. Requirements are rarely written down, and if they are it is often the programmers doing that after speaking to "the business" to find out exactly what is needed. Outside of integrating with external systems, integrating with the rest of the code in the project involves collaboration with the other programmers and the interfaces change when it becomes apparent they need to. Code is reviewed before being added to version control and continuous integration flags up problems as soon as they occur. The idea that a team of humans would need to kick off a build and triage the problems seems quaint and incredibly inefficient now. 

For me, the biggest change is that programmers expect, and are expected, to have a public profile. 

When we solve a problem, we write a blog post about it, redacting any detail that might expose which customer this impacted. We cross post on Substack and Medium. There might be a Github repository with the sample code for the blog post - there will almost certainly be other Github repositories to showcase our work, sometimes complete applications that anyone is welcome to copy. 

We also perform for audiences now, as we share what we've been doing at meet ups, conferences (both community and vendor organised), podcasts, webinars and recorded sessions. I'm pretty sure for the first 5-10 years of my career I didn't even show a customer what I'd built for them, it just got rolled into demos and training carried out by others. Now I show complete strangers from around the world and it seems perfectly normal.

Which is Better?

From the point of view of solving problems and producing solutions, it's almost unrecognisable now. If you hit a problem with anything other than bleeding edge technology, it's incredibly likely that someone else has already hit it and fixed it. And blogged about the fix. And spoken at a conference about it. And maybe created a Github repository with all the code you could possibly need going forward. 

The flip side is that programming is now more of a lifestyle choice than a job. There is an expectation that you will be working on side projects, writing posts and presenting at conferences. Often this will be on top of your actual job, which means that your social life is merely an extension of your professional life and often indistinguishable. Going to the office and working a set number of hours is typically only part of the programmer life these days, which can bring a lot of pressure, especially if you don't see it as a calling.  It can also be a full time job keeping up with the latest developments - frameworks rise and fall, platforms come in and out of favour, or the baddies get a new CEO and become the goodies so you grudgingly have to skill up on their products.

Personally I find it a lot better now that it was when I started, but very I'm lucky in that (a) I enjoy what I do, and (b) I can dedicate large chunks of my own time to all the extra-curricular activities without making my personal life difficult. I'm sure nobody wants to go back to the days when the helpful information was silo'd or didn't exist, but I'd imagine there are some out there who would quite like a return to the days when programming was something you did in private.



Saturday, 14 August 2021

Salesforce++ Top Picks


Salesforce++ is the new streaming service that marries up the excitement of enterprise software with the creativity and spontaneity of reality TV, showcasing exclusive original content that other services can only dream about. 

We've watched them all so you don't have to, so read on for our pick of bunch of August's programming.

90 Day Licenseé

In this show, Salesforce Account Executives are paired up with real life prospects and have 90 days to turn them into paying customers.

As we catch up with the couples in August, Malcolm introduces Clare to his family for the first time. Malcolm's sister, Evelyn, question Clare's intentions, feeling that she is leading Malcolm on to get access to his first call deck.

If you enjoy this show, watch out for 90 Day Licenseé : Happy Ever After? to find out more about previous prospects - did they get the agreement they were looking for, and are they still together with their AE?

American Picklists


Following Salesforce Admins Becky and Taylor from coast to coast as they track down weird and wonderful picklists, and talk to the admins responsible for creating and maintaining them.

August - Becky and Taylor head to rural Iowa to meet solo admin Herman, who works for a local non-profit. While clearing out some old applications that hadn't been opened for years, Herman stumbled across a mint-condition picklist produced for training purposes in 2012, made up of the names of Disney characters. 

Miami ISVs


Drama featuring Sonny Crackit and Rico Tabs, two software engineers based in Miami who spend their weeks helping ISVs fine tune their app exchange offerings, and their weekends on sun-drenched beaches.

In this month's episode, Crackit suffers a concussion after crashing his jet-ski and believes himself to be Sonny Crocket from the Miami Vice TV series. Tabs faces a race against time to stop his colleague from blowing the profits from their last engagement by renting a Ferrari Daytona Spyder.

Deadliest Batch


(Documentary series following the real-life experience of several teams of hard-bitten Apex developers who make a living writing batch jobs for demanding customers)

In August, there's trouble at the family operations. At Munchausen the Slopestring brothers fall out over whether to use Database.Stateful or write information back to the database at the end of each execute method. Meanwhile, at Winter Cove, Calamity Jane Hitchcoski's development team grind around the clock to fill their record quota before tax season ends.

Say Yes to the Apex


Reality series following events at Grossmeadow Software, where the developers try to find the perfect Apex solutions for a different admin and their entourage every week.

August : Can Team Leader Jackie design the perfect Apex for newly single admin Roberto? Roberto has dreamt about replacing his ageing workflow rules with a stylish Apex solution, and is keen to make it happen this year as a tribute to his step-uncle, who died 15 years before Roberto was born. He'll be deploying the code from Honolulu, so is keen that it has a Hawaiian feel to it.


Film of the Month: Bad Multi-Tenant




[While it might not feel like it, streaming services aren't all about reality shows. Salesforce++ features a mix of new and classic movies]

August gets off to a blistering start with a hard hitting classic from the early 90s. Harry Cortez stars as MT, a Salesforce Architect who delights in exploiting loopholes to use more than his fair share of Salesforce resources.  As he closes in on rock bottom, he is given a shot at redemption when he stumbles across a post on Stack Exchange asking for help writing the unit tests for an Apex trigger.

Contains scenes of limit abuse and unbounded SOQL queries.



Sunday, 8 August 2021

Avoiding Returnaggedon


How a company has treated its staff over the last 18 months, and how they treat them over the next few months as traditional workplaces open up, will have a huge impact on their future. Forcing teams back into the office is likely to result in Returnaggedon, where they come back just long enough to hand in their notice.

Now that most legal restrictions in the UK around COVID-19 have been lifted, thoughts are inevitably turning to what happens next in terms of remote work. Many of us are drifting back in for the odd day here and there for meetings, while some CEOs seem determined to revert back to how things were before. Apparently working from home doesn't work for those who want to hustle, and if you can go into a restaurant in New York City, you can come to the office. Although most of the time, the impending switch back to the old normal was immediately pushed back as the delta variant proved to be no respecter of desires or plans - a couple of days ago Amazon were the latest to push back from a September 2021 to January 2022.

Expecting everything to go back to how it was because that's how you liked it seems rather short sighted to me. While many reasons may be given for why everyone needs to be in the same physical location to get their work done, a lot of this will come down to trust, or lack thereof. The pandemic forced many managers to trust that their people were working even when they couldn't stand over them and, while they paid lip service to how well it was all going, that trust really wasn't there. Hence some can't wait to get everyone back in the office where their every move can be watched. Trust begets trust, however, and many employees report not trusting their leadership to manage the return to work safely - last September a survey found only 14% trusted their CEOs and senior leaders to make the correct call, which is pretty shocking. 

It's not just about safety though. People have adjusted to the benefits of part or full time remote working and are reluctant to put the genie back in the bottle.  No commute and saving money are the main reasons that most people want to stay remote, and they won't give that up easily, especially if they can avoid it by simply changing jobs. And people are changing jobs. A lot. So much that it's being called the Great Resignation. A Microsoft survey of 30,000 workers around the world found that 41% of them were considering quitting or changing profession. Imagine losing 41% of your workforce - it's hard to see that as anything other than catastrophic, given how long it takes to fully onboard new employees. While most executives say they don't want things to go back to how they are, around 70% of them want people in the office 3+ days a week, so it's clear that many want it to look an awful lot like it did before, with a few bones thrown to pretend they embrace remote work.

In Salesforce world, the competition for talent has always been intense, and somehow gets hotter every year. Companies need to offer people what they are looking for, or they will miss out to those that do. A survey of 1,000 US office workers in May said 39% would consider quitting if their employer didn't show flex. If you add in to that how easily people can walk into another Salesforce job, it's clear that if employees want to continue with this way of working, an accommodation must be found.  If plans aren't in place to offer remote/hybrid working going forward, it's going to be a bumpy ride!



Saturday, 31 July 2021

The CLI GUI Plays Favourites

 


Introduction


My last change to the CLI GUI was to add the capability to decode a Salesforce CLI command string and regenerate the command page for it. This was the first step towards favourites functionality, so that I could save frequently used commands and quickly re-run them. As usual, it wasn't quite as straightforward as that, but this afternoon I pushed an update to the repository to add support for favourites.

A Few of My Favourite Things


If you are already using the CLI GUI, you'll need to run npm install as I'm using a different mechanism to convert the command string into it's component parameters - string-argv. Previously I had a very complicated regular expression that I found online, but it didn't handle string parameters containing spaces too well, or MacOS directories.

The first change you'll notice when the GUI starts is the new datalist and a couple of buttons. The datalist allows you to select from the favourites you've saved, and you can either Open the command window with the favourite decoded, or run it immediately. As an aside, running a favourite that does something destructive or that can't be undone (like deleting a scratch org) is a pretty dangerous thing to do, so you'll be asked to confirm it. I really only use this for opening orgs without having to go via the command window:


Obviously there won't be anything in the datalist yet, as you'll need to create a favourite or two first.

Favourites are added and removed from the command window, which now has a section at the bottom of the page for this. Once you have set the various parameters, give it a name and click the Save Favourite button:


Note that the directory you are working in is saved with the favourite.

Returning back to the main screen, the new favourite is now available in the datalist, and selecting it enables the buttons:


Clicking the Open button opens the command window with the favourite details, and a button to remove it:



Clicking the Run button first asks you to confirm you really want to do it:



If you choose to continue, the command will immediately execute, in the directory you were in when you saved the favourite, and the output shown in a similar modal to that of the command window:



Right now there's no mechanism to update a favourite - you have to remove the existing one and then save the updated command with the same name. Yes it's a couple more clicks, but think of how grateful you'll be if I do add this capability.

The latest code is in the Github repository, and this week I'm back to the usual test environments of MacOS and Windows 10.  I haven't flogged it to within an inch of its life though, so I'm sure if you look hard enough you'll find something that doesn't work. If you do, feel free to raise an issue.

Related Posts

Saturday, 10 July 2021

The CLI GUI Decodes Command Strings

Introduction

Something I've been meaning to add to the CLI GUI for a while is the ability to enter a CLI command string and decode that into a command page with the appropriate parameters set. This would allow someone to understand more about a command without having to run a help command, match to the parameters, and the additional instructions etc defined in the GUI configuration file can be displayed.

I finally got around to adding that capability this week, which wasn't quite as clunky as I was expecting it to be, although to be fair it is still a little clunky.

The Solution

The decoder is offered as part of a new group named 'Built In' - this is so named because it is added to the configured set of commands in the code and will always be present.


Clicking this opens up the command window with a single input to capture the command string:

In this case it's the command I've used in the past to create an org depdendent package, and made sure to write it down for the next time I needed it,

Clicking the Decode Command changes the page to reflect this command, with any additional instructions. And the first clunky bit, in that I always use the short version of the flags so the command generated in this page doesn't match character for character the one pasted in, although it effectively is the same.


The other clunky part is excluding certain functionality from the page when the command is the decoder, but unless I created a whole new page just for that, I was always going to have to do something along those lines. My command configuration file also now knows about the long and short version of every flag, so that it can decode either. 

The Latest Code

I've pushed the latest code to the Github repository - at the moment it's only tested against MacOS as I won't have access to my Windows machine for a day or so. I can't think of any reason why these changes wouldn't work equally well, but if you hit problems before I get a chance to test, raise an issue in the repo.

One thing to bear in mind is that this can only decode the commands and parameters that it knows about. For example, I haven't configured any of the commands to extract data, so there will be no match found when decoding those. 

Related Posts



Saturday, 3 July 2021

Low Code Still Needs Unit Tests

Introduction

First off let me make clear this is not dumping on low code or some King Canute like attempt to push back the advance of clicks not code in favour of having to write every tiny automation in Apex. When I started working with Salesforce back in 2008, I didn't look at workflow rules and think "Oh nose, I wanted to write a bunch of code to update the contents of a rich text area field", I thought 'That's cool, someone else can configure the simple automation and I get to work on the more challenging scenarios". 

On the developer side we've spent years convincing people that unit tests are a good thing, and we even have test driven development that turns the requirements into tests as a first step, after which we write the code that allows the tests to pass. Some people still moan about having to write tests to deploy to production, but most of us recognise this is a good thing and we'll be grateful we had to do it at some point in the future. 

So when I see messaging (from Salesforce and many others) that not being able to write unit tests is a benefit of whatever Low Code platform is being talked about, it strikes me as an attempt to brand a negative as a positive without explaining the downsides. You might be able to get things into production quicker, but realistically you should be swapping unit test effort for extended QA and UAT effort, not just trousering the difference. If you don't, it's quite likely you are getting bugs into production quicker!

Unit Testing is Important

Unit testing is basically writing code that verifies that other code works as expected. Now that low code includes more and more business logic, and the cyclomatic complexity is increasing, unit testing is something which is needed more than ever. As an aside, I felt the same when Aura components were first introduced and moved a bunch of business logic to the front end, so I did a talk at Dreamforce on unit testing those.  

Unit testing brings the following benefits, which apply equally to all types of code:

  • The nearer you find a bug to the developer, the less it costs to rectify.
  • With good test coverage and appropriate assertions, you can make changes with confidence that if you break behaviour that someone else is relying on, one or more tests will fail (this is the main benefit for me).
  • If someone else makes a change that breaks your code (adding a validation rule is the classic situation here), the next time the unit tests run this will be picked up. 
  • It keeps your users happier, as more bugs are found during the development cycle rather than after the system has been released to them.

Testing No and Low Code

No Code tends to be discrete units that can be used to apply automation, like a workflow rule that sent an email and updated some fields if a record transitioned to a specific state, or a validation rule that checks dependencies between fields. There's no point in unit testing that with many different combinations of record fields, for the same reason that in Apex we don't write unit tests to check that the compiler and run time is working as expected. The workflow engine is tested by Salesforce and we can trust it. Manually running a few records through is fine for testing a scenario like this, as the logic that causes the workflow or validation rule to fire is typically very small and rarely changes.

In Low Code, a number of these kind of items are assembled into some more complex automation in a flow, including conditional logic and loops, which is much closer to traditional code. The medium of expression might be different, but we are now in a world of complexity and reuse, especially if it's a subflow that can be dropped into any other flow. In this world it makes sense to run the flow with a variety of inputs, with the underlying database in a variety of states, and as users with a variety of profiles, and many different combinations if these. Doing all this manually every time there is a change isn't going to be practical. Doing it via test automation tools is possible, but tends to be testing an entire transaction rather than the smallest unit, and it can't happen in production as the changes aren't rolled back at the end of the test.

Right now the only way to do this is in a genuine test environment is to write Apex tests. This somewhat defeats a key benefit of flow for smaller organisations - they would still need a developer on staff to write the unit tests for the flows that the admins have created. (Slightly off topic, I also think it would be hard to find a developer who wanted that job for any length of time, so you'd have to be prepared for some significant churn). Apex can't hook directly into the flow engine in all cases though, so for record triggered there's a compromise that the transaction must actually complete, after which verification that the flow aspect had the desired effect can take place. This is more like an integration test, as there are other aspects of automation taking place that could impact the work done by the flow, but it's definitely better than nothing. Once you have Apex tests, you can take advantage of many existing solutions for scheduled execution, making them part of a deployment pipeline etc.

What Might the Future Hold

Ideally what we need is a Low Code test builder that can execute flows/subflows in isolation and generates actual unit tests, with assertions, that run in an isolated environment where the transactions are rolled back open completion. Generating Apex seems like a reasonable approach to me, as does targeting another engine. Given all the effort that has gone into flow over the last few years, it feels like this should be doable. 

Many years ago when Salesforce was seen as shadow IT, my approach to bring the technology departments into the fold was to tell them how their governance and best practice was needed to ensure that things were done properly and were able to scale. Bringing best practice from the Pro Code world feels like a good way to get everyone on board with the Low Code approach.