“But Apple does it that way”

Adrian Roselli:

It is not uncommon that I raise an accessibility or usability issue with a client’s design or implementation and am met with either “But Google does this”, or “But Apple does this.” Mostly it is the default response to any issue I raise, but it is far worse when it is a reaction to a genuine technical failure or problem real users have identified.

That response does not address the problem I may have raised. It avoids. It offloads responsibility. It declines to even try.

As Jeremy Keith put it:

Cargo cultism is not a strategy.

I Don’t Care What Google or Apple or Whoever Did →

Google Cloud Build + Google Cloud Run: Fixing “ERROR: (gcloud.run.deploy) PERMISSION_DENIED: The caller does not have permission

Google Cloud Build is cool. Google Cloud Run is awesome. But when configuring Google Cloud Build to automatically deploy your built container to Google Cloud Run you might see this error:

ERROR: (gcloud.run.deploy) PERMISSION_DENIED: The caller does not have permission

If you’re seeing this error you forgot to set up the required IAM Permissions for the Cloud Build Service Account. Below I’ll show you the commands to fix this error.

~

As detailed in the Cloud Run documentation, a user needs the following permissions to deploy new Cloud Run services or revisions:

  1. run.services.create and run.services.update on the project level. Typically assigned through the roles/run.admin role.
  2. iam.serviceAccounts.actAs for the Cloud Run runtime service account. By default, this is [email protected]. The permission is typically assigned through the roles/iam.serviceAccountUser role.

By default – for security reasons – the Cloud Build Service Account does not have the permissions to manage Cloud Run, explaining why you’re getting errors.

~

You can set up these required permissions using the Google Cloud Console, yet I prefer to do this from the CLI using the Google Cloud SDK (gcloud), by invoking the commands below:

# Config
GC_PROJECT=your-gcp-project-id
GC_PROJECT_NUMBER=your-gcp-project-number

# Grant the Cloud Run Admin role to the Cloud Build service account
gcloud projects add-iam-policy-binding $GC_PROJECT \
  --member "serviceAccount:[email protected]" \
  --role roles/run.admin

# Grant the IAM Service Account User role to the Cloud Build service account on the Cloud Run runtime service account
gcloud iam service-accounts add-iam-policy-binding \
  [email protected] \
  --member="serviceAccount:[email protected]" \
  --role="roles/iam.serviceAccountUser"

💡 To know the values for GC_PROJECT(_ID) and GC_PROJECT_NUMBER, run gcloud projects list or go to the Home of your project inside Cloud Console.

After running these two commands, re-trigger a build and Google Cloud Build will be able to deploy your built container onto Google Cloud Run.

~

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€4)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Connect to Remote MySQL Server with SSL Certificates from PHP: Fixing the error "Terminated due to signal: ABORT TRAP (6)"


Photo by Clem Onojeghuo on Unsplash

To connect to a MySQL Server that requires SSL from PHP with PDO, you can use this piece of code:

try {
	$db = new PDO('mysql:host=DB_HOST;dbname=DB_NAME', $user, $pass, [
		PDO::MYSQL_ATTR_SSL_KEY => 'path/to/client_private_key',
		PDO::MYSQL_ATTR_SSL_CERT => 'path/to/client_cert',
		PDO::MYSQL_ATTR_SSL_CA => 'path/to/server_ca_cert',
	]);
} catch (PDOException $e) {
	print "Error!: " . $e->getMessage() . "<br/>";
	die();
}

To my surprise I was greeted with an abort signal (not an Exception!) when running this piece of code when trying to connect to a MySQL 5.7 Server on Google Cloud SQL:

Terminated due to signal: ABORT TRAP (6)

Thinking it was a problem with the used certificates I turned to the mysql binary to verify their contents:

$ mysql \
	--ssl-cert='path/to/client_cert' \
	--ssl-key='path/to/client_private_key' \
	--ssl-ca='path/to/server_ca_cert' \
	--host=DB_HOST \
	--user=DB_USERNAME \
	--password

And guess what: that command, of course, worked just fine … but what is the problem then? Is it Google Cloud SQL? Is it PHP acting up?

At the root of the problem is the fact that I’m connecting to the host using an IPv4 address and that the Common Name in the certificate – which one needs to choose manually when generating an SSL Certificate for a Cloud SQL instance – does not match (ref).

To work around this issue you have two options:

  1. (recommended) Connect to your Cloud SQL instance using the Cloud SQL proxy
  2. (not recommended, but needed when solution 1 is not an option) Disable the verification of the server SSL certificate

For the first solution follow Google’s instructions on the Cloud SQL Proxy.

For the second solution, set the PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT option to false:

try {
	$db = new PDO('mysql:host=DB_HOST;dbname=DB_NAME', $user, $pass, [
		PDO::MYSQL_ATTR_SSL_KEY => 'path/to/client_private_key',
		PDO::MYSQL_ATTR_SSL_CERT => 'path/to/client_cert',
		PDO::MYSQL_ATTR_SSL_CA => 'path/to/server_ca_cert',
		PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false,
	]);
} catch (PDOException $e) {
	print "Error!: " . $e->getMessage() . "<br/>";
	die();
}

💁‍♂️ Do note that in this case your connection is encrypted, but you’re not validation the server SSL certificate, and therefore cannot be guaranteed that you’re connecting to the correct server …

With all these set, your PHP code should be able to connect to the MySQL instance without being terminated prematurely …

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Introducing Flutter, Google’s new Mobile UI Framework

Recently Google announced Flutter, their mobile UI framework that “helps developers craft high-quality native interfaces for both iOS and Android”.

Flutter targets the sweet spot of mobile development: performance and platform integrations of native mobile, with high-velocity development and multi-platform reach of portable UI toolkits.

Here’s a simple Hello World app:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Welcome to Flutter',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Welcome to Flutter'),
        ),
        body: new Center(
          child: new Text('Hello World'),
        ),
      ),
    );
  }
}

Quite readable, but could use some JSX imho 😉

Announcing Flutter beta 1: Build beautiful native apps →
A Tour of the Flutter Widget Framework →

How far ahead of Apple Maps is Google Maps?

In succession to Google Maps’s Quiet Transformation, a new – and very extensive and highly interesting – comparison by the same author. He start off by taking a look at the level of detail when it comes to buildings.

But these buildings are more than just a pretty detail—they appear to be the foundation for one of Google Maps’s newest features…

The fun part begins when you start combining these building shapes with places (such as restaurants, coffee shops, etc.) to create “Areas of Interest” which represent commercial corridors. These AOIs are coloured differently on a map, allowing you to quickly recognise ‘m by just glancing at the map.

What about Apple Maps?

With “Areas of Interest”, Google has a feature that Apple doesn’t have. But it’s unclear if Apple could add this feature to its map in the near future.

The challenge for Apple is that AOIs aren’t collected—they’re created. And Apple appears to be missing the ingredients to create AOIs at the same quality, coverage, and scale as Google.

And “Areas of Interest” is just one of the things the author covers …

Google Maps’s Moat →

Google Maps’s Quiet Transformation

Justin O’Beirne kept an eye on how a specific area evolved on Google Maps and on Apple Maps over time:

Patricia’s Green is the centerpiece of a vibrant and trendy neighborhood in central San Francisco, just blocks away from City Hall.

I wrote a script that takes monthly screenshots of Google and Apple Maps. Thirteen months later, we now have a year’s worth of images

On Apple Maps, the area looks much as it did a year ago. But it’s quite a different story on Google Maps: as the months went on, Google continued adding detail.

As a mapping aficionado, I’m intrigued by this kind of stuff 🙂

A year of Google Maps and Apple Maps →

AutoDraw: Fast Drawing for Everyone

After Quickdraw a few months ago – in which A.I. guesses what you are doodling – now comes AutoDraw from Google.

AutoDraw is a new kind of drawing tool. It pairs machine learning with drawings from talented artists to help everyone create anything visual, fast.

AutoDraw’s suggestion tool uses the same technology used in QuickDraw, to guess what you’re trying to draw. Right now, it can guess hundreds of drawings and we look forward to adding more over time.

AutoDraw →

Does Google execute JavaScript?

Stephan Boyer created a website with some JS injected content and waited for Google to crawl it. It got indexed, but without JS execution. Only after having submitted the site manually via the Google Search Console it got indexed with JS executed.

His conclusion:

Google may or may not decide to run your JavaScript, and you don’t want your business to depend on its particular inclination of the day. Do server-side/universal/isomorphic rendering just to be safe.

Now, I don’t wholeheartedly agree with this, as other experiments have already verified that Google indeed indexes JS content. What I think is going on is that Google has 2 crawlers: one dumb/fast one sans JS execution (to quickly index new sites), and a smart/slow one with JS execution (which visits the site later).

Also, I once read a similar article (but cannot seem to find it back) that used window.setTimeout to see how long Google allows the JS execution. If I remember correctly Google will let your scripts run for some time between 30 and 60 seconds max.

Does Google execute JavaScript? →
Does Google crawl dynamic content? →

Related, a few other Google indexing experiments I did:

The Apple-Google shift

google-apple

Elliot-Jay Stocks:

Okay, so I’m considering a switch to Android. No big deal. I’m following in the footsteps of many, many, many others. But what I find interesting outside of my own personal decision is that there seems to be a growing discontent with Apple — especially amongst former so-called fanboys/girls — and, at the same time, a growing appreciation of what Google have been doing, especially from a design perspective.

So I thought I’d try and pick this apart. What’s actually changed?

Apple indeed has been dropping the ball a few times lately. This part on Apple Music is spot on:

What a mess. Sure, it’s not a total failure from an interaction design point of view, but it’s a sub-par effort from a company that should really be far, far, far better than any other steaming music competitors. That Apple Music has been so successful is only down to the ecosystem they’ve cultivated — not because it offers a superior experience.

And that is also exactly why I am staying with Apple: the ecosystem has me quite locked in. Having used an Android for a whole month in late 2015 I started missing the fact that I could answer my phone using my MacBook Pro, my music (bought via iTunes) being available on all my devices (MacBook *and* TV *and* iPhone), iMessage, great/good quality apps in the App Store, Airplay, … (and yes, I do know that there are alternatives to each and every service available, but moving will definitely be quite a big hassle)

The Apple-Google shift →

The New Google Fonts

The new Google Fonts makes it easier than ever to browse our collection of open source designer fonts and learn more about the people who make them. Using the Material Design framework, we created a design that scales across different screen sizes and devices, and updated the entire look and feel of the site, from the overall interactivity all the way down to the logo design.

Google Fonts →