
<rss
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	version="2.0"
>
	<channel>
		<title>Samuel Meuli – Blog</title>
		<description></description>
		<link>https://samuelmeuli.com/blog/</link>
		<lastBuildDate>Thu, 27 Feb 2020 00:00:00 +0000</lastBuildDate>
		
			<language>en-us</language>
		
		
		
		
		
			<atom:link href="https://samuelmeuli.com/blog/index.xml" rel="self" type="application/rss+xml" />
		
		
			<item>
				<title>Finding and Auto-fixing Lint Errors with GitHub Actions</title>
				<description>Using GitHub Actions to enforce clean code in JavaScript, Python, Ruby, Go and Swift projects
</description>
				<link>https://samuelmeuli.com/blog/2020-02-27-finding-and-auto-fixing-lint-errors-with-github-actions/</link>
				<guid>https://samuelmeuli.com/blog/2020-02-27-finding-and-auto-fixing-lint-errors-with-github-actions/</guid>
				<pubDate>Thu, 27 Feb 2020 00:00:00 +0000</pubDate>
				
				
					<category>Tutorials</category>
				
					<category>GitHub</category>
				
					<category>CI</category>
				
				<content:encoded>
					&lt;![CDATA[
					&lt;p&gt;Using GitHub Actions to enforce clean code in JavaScript, Python, Ruby, Go and Swift projects&lt;/p&gt;
&lt;p&gt;Linters are important tools for detecting potential errors and maintaining a consistent code style in a project. Unfortunately, it can happen that a contributor creates commits without running the linter first and that style violations are merged.&lt;/p&gt;
&lt;p&gt;To make sure that contributions are linted, the code analysis can be performed as part of a CI pipeline. Merging can even be blocked as long as linting errors are unresolved.&lt;/p&gt;
&lt;p&gt;With &lt;a href=&#34;https://github.com/features/actions&#34;&gt;Actions&lt;/a&gt;, GitHub launched their own CI service last year. By setting up my &lt;strong&gt;&lt;a href=&#34;https://github.com/samuelmeuli/lint-action&#34;&gt;Lint Action&lt;/a&gt;&lt;/strong&gt;, GitHub Actions can be used to lint code whenever a change is pushed. The action not only shows the &lt;strong&gt;lint result on commits and PRs&lt;/strong&gt; but also creates inline &lt;strong&gt;code annotations for each linting error&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./commit-annotation.png&#34; alt=&#34;Screenshot of a commit annotation&#34;&gt;&lt;/p&gt;
&lt;p&gt;These annotations, together with the action&amp;rsquo;s &lt;strong&gt;auto-fix feature&lt;/strong&gt;, make it easy for both maintainers and contributors to keep the code style in a repository consistent.&lt;/p&gt;
&lt;h3 id=&#34;using-the-lint-action&#34;&gt;Using the Lint Action&lt;/h3&gt;
&lt;p&gt;To enable the Lint Action in your repository, create a GitHub Actions workflow in the &lt;code&gt;.github/workflows/&lt;/code&gt; directory (e.g. named &lt;code&gt;lint.yml&lt;/code&gt;). The file should use a structure similar to the following:&lt;/p&gt;

&lt;div class=&#34;file-name&#34;&gt;
	&lt;code&gt;
		.github/workflows/lint.yml
	&lt;/code&gt;
&lt;/div&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;k&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Lint&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;on&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;push&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;jobs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;run-linters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Run&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;linters&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;runs-on&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;ubuntu-latest&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;k&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Check&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;out&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;repository&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;uses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;actions/checkout@v2&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# TODO: Install your linters here&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;k&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Run&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;linters&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;uses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;samuelmeuli/lint-action@v1&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;github_token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;${{&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;secrets.github_token&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;}}&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# TODO: Enable your linters here&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The Lint Action supports linters and formatters for a variety of programming languages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CSS&lt;/strong&gt; (stylelint)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Go&lt;/strong&gt; (&lt;code&gt;gofmt&lt;/code&gt;, &lt;code&gt;golint&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JavaScript&lt;/strong&gt; (ESLint, Prettier)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Python&lt;/strong&gt; (Black, Flake8, Mypy)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ruby&lt;/strong&gt; (RuboCop)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Swift&lt;/strong&gt; (SwiftFormat, SwiftLint)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Furthermore, the action can easily be extended to support other languages and tools. A contributing guide can be found &lt;a href=&#34;https://github.com/samuelmeuli/lint-action#development&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;showing-lint-errors-on-commitsprs&#34;&gt;Showing Lint Errors on Commits/PRs&lt;/h3&gt;
&lt;p&gt;For the Lint Action to work, you first need to install the linters you wish to use on the virtual machine. The following example shows how this is done for Python. Code is linted with Flake8 and formatted with Black:&lt;/p&gt;

&lt;div class=&#34;file-name&#34;&gt;
	&lt;code&gt;
		.github/workflows/lint.yml
	&lt;/code&gt;
&lt;/div&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;  name: Lint

  on: push

  jobs:
    run-linters:
      name: Run linters
      runs-on: ubuntu-latest

      steps:
        - name: Check out Git repository
          uses: actions/checkout@v2

&lt;span class=&#34;gd&#34;&gt;-       # TODO: Install your linters here
&lt;/span&gt;&lt;span class=&#34;gd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+       - name: Set up Python
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+         uses: actions/setup-python@v1
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+         with:
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+           python-version: 3.8
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+       - name: Install Python dependencies
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+         run: pip install black flake8
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt;
        - name: Run linters
          uses: samuelmeuli/lint-action@v1
          with:
            github_token: ${{ secrets.github_token }}
&lt;span class=&#34;gd&#34;&gt;-           # TODO: Enable your linters here
&lt;/span&gt;&lt;span class=&#34;gd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+           black: true
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+           flake8: true
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The approach is the same for other programming languages and linters. You can find more examples &lt;a href=&#34;https://github.com/samuelmeuli/lint-action#examples&#34;&gt;in the action&amp;rsquo;s docs&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;viewing-lint-results&#34;&gt;Viewing Lint Results&lt;/h3&gt;
&lt;p&gt;Every time somebody pushes to your repository, the action will now lint the project. Using GitHub&amp;rsquo;s &lt;a href=&#34;https://developer.github.com/v3/checks/runs&#34;&gt;Check Runs API&lt;/a&gt;, the commit will be annotated with the lint result. You can even inspect the specific lines of code where style violations were found.&lt;/p&gt;
&lt;p&gt;If the commit is part of a pull request, GitHub will automatically pick up the latest check and display it in a user-friendly way, showing the committer or maintainer whether the PR requires further inspection before a merge can be made:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./check-runs.png&#34; alt=&#34;Screenshot of a check run&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;auto-fixing-errors&#34;&gt;Auto-fixing Errors&lt;/h3&gt;
&lt;p&gt;Besides showing lint errors, the Lint Action can also fix some of the issues automatically. This is done by running the linter commands with the corresponding auto-fix arguments and creating a bot commit of the changed files.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./auto-fix.png&#34; alt=&#34;Screenshot of an auto-fix commit&#34;&gt;&lt;/p&gt;
&lt;p&gt;Setting up auto-fixing is easy: All you need to do is set the action&amp;rsquo;s &lt;code&gt;auto_fix&lt;/code&gt; option to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;auto_fix&lt;/code&gt; value can also be determined dynamically using &lt;a href=&#34;https://help.github.com/en/actions/automating-your-workflow-with-github-actions/contexts-and-expression-syntax-for-github-actions&#34;&gt;GitHub Actions&amp;rsquo; expression syntax&lt;/a&gt;. For instance, you might not want any auto-fix commits on your &lt;code&gt;master&lt;/code&gt; branch. To only create such bot commits on PR branches, you can configure the action as follows:&lt;/p&gt;

&lt;div class=&#34;file-name&#34;&gt;
	&lt;code&gt;
		.github/workflows/lint.yml
	&lt;/code&gt;
&lt;/div&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;  name: Lint

&lt;span class=&#34;gd&#34;&gt;- on: push
&lt;/span&gt;&lt;span class=&#34;gd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+ on: [push, pull_request]
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt;
  jobs:
    run-linters:
      name: Run linters
      runs-on: ubuntu-latest

      steps:
        - name: Check out Git repository
          uses: actions/checkout@v2

        - name: Set up Python
          uses: actions/setup-python@v1
          with:
            python-version: 3.8

        - name: Install Python dependencies
          run: pip install black flake8

        - name: Run linters
          uses: samuelmeuli/lint-action@v1
          with:
            github_token: ${{ secrets.github_token }}
&lt;span class=&#34;gi&#34;&gt;+           auto_fix: ${{ github.event_name == &amp;#39;pull_request&amp;#39; }}
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt;            black: true
            flake8: true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Please note that GitHub Actions currently has limitations with &lt;code&gt;pull_request&lt;/code&gt; events triggered by forks. See &lt;a href=&#34;https://github.com/samuelmeuli/lint-action/issues/13&#34;&gt;this issue&lt;/a&gt; for details.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;making-checks-mandatory&#34;&gt;Making Checks Mandatory&lt;/h3&gt;
&lt;p&gt;After your checks have run for the first time, you can choose to make them a requirement for pull requests and block merging while there are linting errors. You can configure this in your repository settings under &amp;ldquo;Branches&amp;rdquo; → &amp;ldquo;Add rule&amp;rdquo; → &amp;ldquo;Require status checks to pass before merging&amp;rdquo;.&lt;/p&gt;
					]]&gt;
				</content:encoded>
			</item>
		
			<item>
				<title>Notarizing Your Electron App</title>
				<description>A guide on notarizing Electron apps for macOS with electron-builder
</description>
				<link>https://samuelmeuli.com/blog/2019-12-28-notarizing-your-electron-app/</link>
				<guid>https://samuelmeuli.com/blog/2019-12-28-notarizing-your-electron-app/</guid>
				<pubDate>Sat, 28 Dec 2019 00:00:00 +0000</pubDate>
				
				
					<category>Tutorials</category>
				
					<category>JavaScript</category>
				
					<category>Electron</category>
				
					<category>macOS</category>
				
				<content:encoded>
					&lt;![CDATA[
					&lt;p&gt;A guide on notarizing Electron apps for macOS with &lt;code&gt;electron-builder&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;With the release of macOS Catalina (10.15), Apple made app hardening and notarization mandatory for apps distributed outside the Mac App Store.&lt;/p&gt;
&lt;p&gt;Like app sandboxing, the &lt;strong&gt;Hardened Runtime&lt;/strong&gt; is a security feature that restricts your app from utilizing certain system features. Exceptions can also be defined using code signing entitlements.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Notarization&lt;/strong&gt; is an automated security check by Apple, which involves their servers scanning your app for malicious content and code signing issues. App notarization requires your app to use the Hardened Runtime.&lt;/p&gt;
&lt;p&gt;Thankfully, hardening and notarizing Electron apps has become a pretty simple process. This tutorial assumes that &lt;a href=&#34;https://samuelmeuli.com/blog/2019-04-07-packaging-and-publishing-an-electron-app/&#34;&gt;you&amp;rsquo;ve already set up &lt;code&gt;electron-builder&lt;/code&gt;&lt;/a&gt; in your project. The build tool can be configured to harden your app for you, and the &lt;a href=&#34;https://github.com/electron/electron-notarize&#34;&gt;&lt;code&gt;electron-notarize&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://github.com/karaggeorge/electron-builder-notarize&#34;&gt;&lt;code&gt;electron-builder-notarize&lt;/code&gt;&lt;/a&gt; packages can take care of notarizing your app:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;electron-builder&lt;/code&gt; builds and signs your app to use the Hardened Runtime&lt;/li&gt;
&lt;li&gt;&lt;code&gt;electron-notarize&lt;/code&gt; wraps Apple&amp;rsquo;s &lt;code&gt;altool&lt;/code&gt; CLI and uses it to notarize your app&lt;/li&gt;
&lt;li&gt;&lt;code&gt;electron-builder-notarize&lt;/code&gt; wraps &lt;code&gt;electron-notarize&lt;/code&gt; and simplifies its usage with &lt;code&gt;electron-builder&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;app-configuration&#34;&gt;App Configuration&lt;/h3&gt;
&lt;p&gt;To get started, install &lt;code&gt;electron-builder-notarize&lt;/code&gt; in your Electron app:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;yarn add --dev electron-builder-notarize
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To get notarization to work, add the following options in your &lt;code&gt;package.json&lt;/code&gt; file:&lt;/p&gt;

&lt;div class=&#34;file-name&#34;&gt;
	&lt;code&gt;
		package.json
	&lt;/code&gt;
&lt;/div&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
	&lt;span class=&#34;nt&#34;&gt;&amp;#34;build:&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;#34;afterSign&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;electron-builder-notarize&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;#34;mac&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
			&lt;span class=&#34;nt&#34;&gt;&amp;#34;hardenedRuntime&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
		&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, create or update your &lt;code&gt;build/entitlements.mac.plist&lt;/code&gt; file with the following code signing entitlements, which are required for Electron to work:&lt;/p&gt;

&lt;div class=&#34;file-name&#34;&gt;
	&lt;code&gt;
		build/entitlements.mac.plist
	&lt;/code&gt;
&lt;/div&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;UTF-8&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;span class=&#34;cp&#34;&gt;&amp;lt;!DOCTYPE plist PUBLIC &amp;#34;-//Apple//DTD PLIST 1.0//EN&amp;#34; &amp;#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd&amp;#34;&amp;gt;&lt;/span&gt;
&lt;span class=&#34;nt&#34;&gt;&amp;lt;plist&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;version=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
	&lt;span class=&#34;nt&#34;&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;com.apple.security.cs.allow-jit&lt;span class=&#34;nt&#34;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;com.apple.security.cs.allow-unsigned-executable-memory&lt;span class=&#34;nt&#34;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;com.apple.security.cs.allow-dyld-environment-variables&lt;span class=&#34;nt&#34;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;
	&lt;span class=&#34;nt&#34;&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class=&#34;nt&#34;&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;authentication&#34;&gt;Authentication&lt;/h3&gt;
&lt;p&gt;Now, you&amp;rsquo;ll want to give &lt;code&gt;electron-builder-notarize&lt;/code&gt; permission to notarize your app. A secure way to do so is using the App Store Connect API.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Sign in to App Store Connect and open the &lt;a href=&#34;https://appstoreconnect.apple.com/access/api&#34;&gt;API key page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Create a new API key by clicking on the &amp;ldquo;+&amp;rdquo; symbol. Set access permissions to &amp;ldquo;App Manager&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Download the key file and move it into the &lt;code&gt;~/private_keys/&lt;/code&gt; directory, where &lt;code&gt;altool&lt;/code&gt; will be able to find it&lt;/li&gt;
&lt;li&gt;Copy your Issuer ID (1) and Key ID (2):&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;./app-store-connect-api-page.png&#34; alt=&#34;App Store Connect API page&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;notarization&#34;&gt;Notarization&lt;/h3&gt;
&lt;p&gt;If you pass the credentials you just copied as environment variables to &lt;code&gt;electron-builder&lt;/code&gt;, your app should be built and notarized successfully:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;nv&#34;&gt;API_KEY_ID&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;...&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;API_KEY_ISSUER_ID&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;...&amp;#34;&lt;/span&gt; yarn run electron-builder --mac
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Please note that the notarization process might take a few minutes.&lt;/p&gt;
&lt;p&gt;To avoid your API information being visible in the terminal history, you can use a package like &lt;a href=&#34;https://github.com/motdotla/dotenv&#34;&gt;dotenv&lt;/a&gt; to read your environment variables from a file instead.&lt;/p&gt;
&lt;h3 id=&#34;sources&#34;&gt;Sources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/electron/electron-notarize&#34;&gt;&lt;code&gt;electron-notarize&lt;/code&gt; docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://kilianvalkhof.com/2019/electron/notarizing-your-electron-application&#34;&gt;Notarizing your Electron application&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
					]]&gt;
				</content:encoded>
			</item>
		
			<item>
				<title>Automating the Release of Electron Apps</title>
				<description>Using GitHub Actions to automatically build and release your Electron app for macOS, Windows and Linux
</description>
				<link>https://samuelmeuli.com/blog/2019-11-17-automating-the-release-of-electron-apps/</link>
				<guid>https://samuelmeuli.com/blog/2019-11-17-automating-the-release-of-electron-apps/</guid>
				<pubDate>Sun, 17 Nov 2019 00:00:00 +0000</pubDate>
				
				
					<category>JavaScript</category>
				
					<category>Electron</category>
				
					<category>GitHub</category>
				
					<category>CI</category>
				
				<content:encoded>
					&lt;![CDATA[
					&lt;p&gt;Using GitHub Actions to automatically build and release your Electron app for macOS, Windows and Linux&lt;/p&gt;
&lt;p&gt;One major advantage of building desktop apps with Electron is that your app works on multiple platforms with a single codebase. Unfortunately, there are some challenges in building an app for multiple operating systems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Setting up and building your app on VMs is somewhat cumbersome&lt;/li&gt;
&lt;li&gt;Mac apps can only be built on macOS, which not every developer has access to&lt;/li&gt;
&lt;li&gt;Building Windows apps on other platforms has become more difficult with the release of macOS Catalina, which has dropped support for 32-bit apps and therefore breaks Wine&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A nice way to solve such problems is to use the recently launched &lt;a href=&#34;https://github.com/features/actions&#34;&gt;GitHub Actions&lt;/a&gt;, which allows you to run CI/CD workflows on multiple operating systems, including macOS, Windows and Ubuntu, which is exactly what you need for building Electron apps.&lt;/p&gt;
&lt;p&gt;For this purpose, I created the &lt;a href=&#34;https://github.com/samuelmeuli/action-electron-builder&#34;&gt;Electron Builder Action&lt;/a&gt;. After setting up the action, your pipeline will automatically build your app on GitHub&amp;rsquo;s servers using &lt;a href=&#34;https://github.com/electron-userland/electron-builder&#34;&gt;&lt;code&gt;electron-builder&lt;/code&gt;&lt;/a&gt;. When the action detects that you&amp;rsquo;ve tagged a commit with a version identifier, it can even release the packaged app for you.&lt;/p&gt;
&lt;p&gt;You can read more about using the action &lt;a href=&#34;https://github.com/samuelmeuli/action-electron-builder&#34;&gt;here&lt;/a&gt;, and see an example of how it&amp;rsquo;s used in the repository of my &lt;a href=&#34;https://github.com/samuelmeuli/mini-diary&#34;&gt;Mini Diary&lt;/a&gt; Electron app.&lt;/p&gt;
					]]&gt;
				</content:encoded>
			</item>
		
			<item>
				<title>Removing Dead Keys on macOS</title>
				<description>A tutorial on re-mapping dead keys on macOS keyboard layouts
</description>
				<link>https://samuelmeuli.com/blog/2019-11-17-removing-dead-keys-on-macos/</link>
				<guid>https://samuelmeuli.com/blog/2019-11-17-removing-dead-keys-on-macos/</guid>
				<pubDate>Sun, 17 Nov 2019 00:00:00 +0000</pubDate>
				
				
					<category>Tutorials</category>
				
					<category>macOS</category>
				
				<content:encoded>
					&lt;![CDATA[
					&lt;p&gt;A tutorial on re-mapping dead keys on macOS keyboard layouts&lt;/p&gt;
&lt;p&gt;Depending on the macOS keyboard layout you&amp;rsquo;re using, you might have &amp;ldquo;dead keys&amp;rdquo;. A dead key represents a symbol that isn&amp;rsquo;t a full character and therefore isn&amp;rsquo;t immediately inserted into the text when typed. Examples of dead keys are &lt;code&gt;^&lt;/code&gt;, &lt;code&gt;`&lt;/code&gt; and &lt;code&gt;~&lt;/code&gt;. For instance, when typing &lt;code&gt;`&lt;/code&gt; followed by &lt;code&gt;a&lt;/code&gt;, macOS will insert &lt;code&gt;à&lt;/code&gt; instead.&lt;/p&gt;
&lt;p&gt;For programmers, this behavior is often undesirable. For example, the tilde (&lt;code&gt;~&lt;/code&gt;) is a useful shortcut for the &lt;code&gt;$HOME&lt;/code&gt; shell variable, and the backtick (&lt;code&gt;`&lt;/code&gt;) is used for template literals in JavaScript. Therefore, if you&amp;rsquo;re not using the symbols in your language, it might be preferable if these characters were inserted immediately when typed.&lt;/p&gt;
&lt;p&gt;Fortunately, reconfiguring your keyboard layout to remove these dead keys is relatively easy. The &lt;a href=&#34;https://software.sil.org/ukelele&#34;&gt;Ukelele&lt;/a&gt; app can help you with this task:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download and install Ukelele from &lt;a href=&#34;https://software.sil.org/ukelele/#downloads&#34;&gt;its website&lt;/a&gt; or using &lt;code&gt;brew cask install ukelele&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open the Ukelele app.&lt;/li&gt;
&lt;li&gt;In the application menu, select &lt;code&gt;File&lt;/code&gt; → &lt;code&gt;New From Current Input Source&lt;/code&gt;. This will detect your keyboard layout and create a copy that you can modify.&lt;/li&gt;
&lt;li&gt;In the main window, Ukelele displays your layout with the dead keys highlighted in red. Right-click each of your dead keys, select the corresponding modifier key if necessary (e.g. the shift or option key) and enter the key&amp;rsquo;s value at the bottom of the dialog. This will change the key&amp;rsquo;s behavior to insert the symbol right away.&lt;/li&gt;
&lt;li&gt;Once you&amp;rsquo;ve re-mapped all dead keys, save your keyboard layout and copy it to the &lt;code&gt;~/Library/Keyboard Layouts&lt;/code&gt; directory.&lt;/li&gt;
&lt;li&gt;Reboot your Mac.&lt;/li&gt;
&lt;li&gt;Open the System Preferences and navigate to &lt;code&gt;Keyboard&lt;/code&gt; → &lt;code&gt;Input Sources&lt;/code&gt; → &lt;code&gt;+&lt;/code&gt;. Your custom keyboard layout can be found under the language it&amp;rsquo;s based on. You can now add your new keyboard layout and activate it from the menu bar.&lt;/li&gt;
&lt;/ol&gt;
					]]&gt;
				</content:encoded>
			</item>
		
			<item>
				<title>Publishing an Electron App on the Mac App Store</title>
				<description>Having your Electron app on the Mac App Store makes it simpler for users to discover and download your app. This guide explains how to get your app listed
</description>
				<link>https://samuelmeuli.com/blog/2019-04-09-publishing-an-electron-app-on-the-mac-app-store/</link>
				<guid>https://samuelmeuli.com/blog/2019-04-09-publishing-an-electron-app-on-the-mac-app-store/</guid>
				<pubDate>Tue, 09 Apr 2019 00:00:00 +0000</pubDate>
				
				
					<category>Tutorials</category>
				
					<category>JavaScript</category>
				
					<category>Electron</category>
				
					<category>macOS</category>
				
				<content:encoded>
					&lt;![CDATA[
					&lt;p&gt;Having your Electron app on the Mac App Store makes it simpler for users to discover and download your app. This guide explains how to get your app listed&lt;/p&gt;
&lt;p&gt;I went through this process when publishing &lt;a href=&#34;https://minidiary.app&#34;&gt;Mini Diary&lt;/a&gt;. &lt;code&gt;electron-builder&lt;/code&gt;&#39;s docs aren&amp;rsquo;t great and existing tutorials are overly complicated or outdated. This guide aims to provide simple and comprehensive instructions on how to publish an app on the Mac App Store.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; This tutorial assumes that you have followed &lt;em&gt;all&lt;/em&gt; steps outlined in the &lt;a href=&#34;https://samuelmeuli.com/blog/2019-04-07-packaging-and-publishing-an-electron-app/&#34;&gt;previous post on packaging and publishing Electron apps&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;1-electron-builder-configuration&#34;&gt;1. &lt;code&gt;electron-builder&lt;/code&gt; Configuration&lt;/h3&gt;
&lt;p&gt;To generate a package for the Mac App Store every time you run your &lt;code&gt;build&lt;/code&gt; script, extend the &lt;code&gt;electron-builder&lt;/code&gt; configuration in your &lt;code&gt;package.json&lt;/code&gt; file by the following settings:&lt;/p&gt;

&lt;div class=&#34;file-name&#34;&gt;
	&lt;code&gt;
		package.json
	&lt;/code&gt;
&lt;/div&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
	&lt;span class=&#34;nt&#34;&gt;&amp;#34;build&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;#34;mac&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
			&lt;span class=&#34;nt&#34;&gt;&amp;#34;target&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;dmg&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;mas&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;zip&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
			&lt;span class=&#34;nt&#34;&gt;&amp;#34;electronLanguages&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;en&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
		&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;&amp;quot;mas&amp;quot;&lt;/code&gt; key in the &lt;code&gt;&amp;quot;target&amp;quot;&lt;/code&gt; array configures &lt;code&gt;electron-builder&lt;/code&gt; to build your app for the Mac App Store (MAS) in addition to the default formats. Specifying &lt;code&gt;&amp;quot;electronLanguages&amp;quot;&lt;/code&gt; affects which languages are shown on your app&amp;rsquo;s MAS page. If you don&amp;rsquo;t set this parameter, a long list of different languages will be displayed by default. You can find the language keys of the different locales in the &lt;a href=&#34;https://electronjs.org/docs/api/locales&#34;&gt;Electron docs&lt;/a&gt; (make sure you replace hyphens with underlines).&lt;/p&gt;
&lt;h3 id=&#34;2-app-id&#34;&gt;2. App ID&lt;/h3&gt;
&lt;p&gt;Next, your MAS app needs an App ID. You can generate one in the &lt;a href=&#34;https://developer.apple.com/account/resources/identifiers/list&#34;&gt;Apple Developer Portal&lt;/a&gt;. App IDs are usually of the form &lt;code&gt;com.yourcompany.yourapp&lt;/code&gt;. This App ID needs to be the same as the one you specified in your &lt;code&gt;package.json&lt;/code&gt; file under the &lt;code&gt;build.appId&lt;/code&gt; key.&lt;/p&gt;
&lt;h3 id=&#34;3-entitlement-files&#34;&gt;3. Entitlement Files&lt;/h3&gt;
&lt;p&gt;All apps distributed on the Mac App Store need to be &lt;a href=&#34;https://developer.apple.com/app-sandboxing&#34;&gt;sandboxed&lt;/a&gt;. As the developer of such an app, you need to specify the privileges that your app needs to function, and macOS will prevent it from using any other system functionality.&lt;/p&gt;
&lt;p&gt;To specify the privileges required by your app, create the following file in your project&amp;rsquo;s &lt;code&gt;build&lt;/code&gt; folder:&lt;/p&gt;

&lt;div class=&#34;file-name&#34;&gt;
	&lt;code&gt;
		build/entitlements.mas.plist
	&lt;/code&gt;
&lt;/div&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;UTF-8&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;span class=&#34;cp&#34;&gt;&amp;lt;!DOCTYPE plist PUBLIC &amp;#34;-//Apple//DTD PLIST 1.0//EN&amp;#34; &amp;#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd&amp;#34;&amp;gt;&lt;/span&gt;
&lt;span class=&#34;nt&#34;&gt;&amp;lt;plist&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;version=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#34;nt&#34;&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
	&lt;span class=&#34;nt&#34;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;com.apple.security.app-sandbox&lt;span class=&#34;nt&#34;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
	&lt;span class=&#34;nt&#34;&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;
	&lt;span class=&#34;c&#34;&gt;&amp;lt;!-- Add entitlements here --&amp;gt;&lt;/span&gt;
&lt;span class=&#34;nt&#34;&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class=&#34;nt&#34;&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, add all entitlements your app needs to this file (see &lt;a href=&#34;https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/AboutEntitlements.html&#34;&gt;Apple&amp;rsquo;s docs&lt;/a&gt; for possible entitlements). The simplest way to do so is using Xcode. For example, if your Electron app needs to be able to read specific files using an open dialog, your entitlements file should look like this:&lt;/p&gt;

&lt;div class=&#34;file-name&#34;&gt;
	&lt;code&gt;
		build/entitlements.mas.plist
	&lt;/code&gt;
&lt;/div&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;UTF-8&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;span class=&#34;cp&#34;&gt;&amp;lt;!DOCTYPE plist PUBLIC &amp;#34;-//Apple//DTD PLIST 1.0//EN&amp;#34; &amp;#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd&amp;#34;&amp;gt;&lt;/span&gt;
&lt;span class=&#34;nt&#34;&gt;&amp;lt;plist&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;version=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#34;nt&#34;&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
	&lt;span class=&#34;nt&#34;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;com.apple.security.app-sandbox&lt;span class=&#34;nt&#34;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
	&lt;span class=&#34;nt&#34;&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;
	&lt;span class=&#34;nt&#34;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;com.apple.security.files.user-selected.read-only&lt;span class=&#34;nt&#34;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
	&lt;span class=&#34;nt&#34;&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;
&lt;span class=&#34;nt&#34;&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class=&#34;nt&#34;&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you&amp;rsquo;re also distributing your app outside the Mac App Store and intend to sandbox that version as well, create a file named &lt;code&gt;entitlements.mac.plist&lt;/code&gt; in the &lt;code&gt;build&lt;/code&gt; directory with the same content as the &lt;code&gt;entitlements.mas.plist&lt;/code&gt; file.&lt;/p&gt;
&lt;h3 id=&#34;4-provisioning-profile&#34;&gt;4. Provisioning Profile&lt;/h3&gt;
&lt;p&gt;Navigate to the &lt;a href=&#34;https://developer.apple.com/account/resources/profiles/list&#34;&gt;&amp;ldquo;Profile&amp;rdquo; section of the Apple Developer Portal&lt;/a&gt;. Create two provisioning profiles for your app: A &amp;ldquo;Mac App Development&amp;rdquo; and a &amp;ldquo;Mac App Store&amp;rdquo; provisioning profile. Download the two files and make sure you remember which one is for development and which one is for production (e.g. by naming them &lt;code&gt;dev.provisionprofile&lt;/code&gt; and &lt;code&gt;prod.provisionprofile&lt;/code&gt;).&lt;/p&gt;
&lt;h3 id=&#34;5-testing&#34;&gt;5. Testing&lt;/h3&gt;
&lt;h4 id=&#34;development&#34;&gt;Development&lt;/h4&gt;
&lt;p&gt;To test the MAS build, place &lt;code&gt;dev.provisionprofile&lt;/code&gt; in your project&amp;rsquo;s root. Extend your &lt;code&gt;electron-builder&lt;/code&gt; config in &lt;code&gt;package.json&lt;/code&gt; by the following:&lt;/p&gt;

&lt;div class=&#34;file-name&#34;&gt;
	&lt;code&gt;
		package.json
	&lt;/code&gt;
&lt;/div&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
	&lt;span class=&#34;nt&#34;&gt;&amp;#34;build&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;#34;mas&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
			&lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;development&amp;#34;&lt;/span&gt;
		&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you&amp;rsquo;re also sandboxing your non-MAS Mac build, you should also add &lt;code&gt;&amp;quot;type&amp;quot;: &amp;quot;development&amp;quot;&lt;/code&gt; to the &lt;code&gt;build.mac&lt;/code&gt; config.&lt;/p&gt;
&lt;p&gt;Run &lt;code&gt;yarn build&lt;/code&gt;. You should now be able to open your packaged MAS app (placed in the &lt;code&gt;dist/mas&lt;/code&gt; directory).&lt;/p&gt;
&lt;h4 id=&#34;production&#34;&gt;Production&lt;/h4&gt;
&lt;p&gt;If everything is working as expected, you can build your app for production. Simply replace &lt;code&gt;dev.provisionprofile&lt;/code&gt; with &lt;code&gt;prod.provisionprofile&lt;/code&gt;, remove the &lt;code&gt;&amp;quot;type&amp;quot;: &amp;quot;development&amp;quot;&lt;/code&gt; lines from your &lt;code&gt;package.json&lt;/code&gt; again and run the &lt;code&gt;yarn build&lt;/code&gt; script. Please note that &lt;strong&gt;you will not be able to open the built production app&lt;/strong&gt; (it will crash on launch). This is the &lt;a href=&#34;https://github.com/electron-userland/electron-builder/issues/1967#issuecomment-323569575&#34;&gt;expected behavior&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;6-upload-to-mas&#34;&gt;6. Upload to MAS&lt;/h3&gt;
&lt;p&gt;Go to &lt;a href=&#34;https://appstoreconnect.apple.com&#34;&gt;App Store Connect&lt;/a&gt; and open &amp;ldquo;My Apps&amp;rdquo;. Create a new entry for your Mac app.&lt;/p&gt;
&lt;p&gt;Open Xcode. From the menu, launch Xcode → Open Developer Tool → Application Loader and follow the steps from there. This tool will upload your app to App Store Connect.&lt;/p&gt;
&lt;p&gt;Finally, go back to your app listing in App Store Connect, fill in all information about your app and select the uploaded build. Make sure you explain thoroughly why your app needs the specified entitlements. You can now submit your app for review, which usually takes about a day. Once your app is accepted, you can publish your app on the Mac App Store.&lt;/p&gt;
&lt;h3 id=&#34;sources&#34;&gt;Sources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.electron.build&#34;&gt;&lt;code&gt;electron-builder&lt;/code&gt; docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://medium.com/@jondot/shipping-electron-apps-to-mac-app-store-with-electron-builder-e960d46148ec&#34;&gt;Shipping Electron Apps to Mac App Store with Electron Builder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://medium.com/@flaqueEau/releasing-an-electron-app-on-the-mac-app-store-c32dfcd9c2bd&#34;&gt;Releasing an Electron app on the Mac App Store&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
					]]&gt;
				</content:encoded>
			</item>
		
			<item>
				<title>Packaging and Publishing an Electron App</title>
				<description>Electron simplifies the development of cross-platform desktop apps. Unfortunately, packaging and releasing an Electron app for the different platforms is not a straightforward task. This post aims to guide you through the process
</description>
				<link>https://samuelmeuli.com/blog/2019-04-07-packaging-and-publishing-an-electron-app/</link>
				<guid>https://samuelmeuli.com/blog/2019-04-07-packaging-and-publishing-an-electron-app/</guid>
				<pubDate>Sun, 07 Apr 2019 00:00:00 +0000</pubDate>
				
				
					<category>Tutorials</category>
				
					<category>JavaScript</category>
				
					<category>Electron</category>
				
				<content:encoded>
					&lt;![CDATA[
					&lt;p&gt;Electron simplifies the development of cross-platform desktop apps. Unfortunately, packaging and releasing an Electron app for the different platforms is not a straightforward task. This post aims to guide you through the process&lt;/p&gt;
&lt;h3 id=&#34;packaging&#34;&gt;Packaging&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/electron-userland/electron-builder&#34;&gt;&lt;code&gt;electron-builder&lt;/code&gt;&lt;/a&gt; is a third-party tool that facilitates the process of packaging an Electron app. The tool handles various tasks required for building a production-ready app, like the inclusion of native dependencies, code signing, upload to a download server, and the inclusion of an auto-updater tool.&lt;/p&gt;
&lt;p&gt;Run the following command to add &lt;code&gt;electron-builder&lt;/code&gt; to your Electron project:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;yarn add --dev electron-builder
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, add the following scripts to your &lt;code&gt;package.json&lt;/code&gt; file:&lt;/p&gt;

&lt;div class=&#34;file-name&#34;&gt;
	&lt;code&gt;
		package.json
	&lt;/code&gt;
&lt;/div&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
	&lt;span class=&#34;nt&#34;&gt;&amp;#34;scripts:&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;#34;postinstall&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;electron-builder install-app-deps&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;#34;build&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;electron-builder --mac --windows --linux&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;#34;release&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;electron-builder --mac --windows --linux --publish always&amp;#34;&lt;/span&gt;
	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;postinstall&lt;/code&gt; script will execute after every &lt;code&gt;yarn install&lt;/code&gt; and makes sure that native dependencies match your app&amp;rsquo;s version of Electron. The &lt;code&gt;build&lt;/code&gt; script can be used to package your app for all specified platforms. The &lt;code&gt;release&lt;/code&gt; script builds the app and publishes it on your download server.&lt;/p&gt;
&lt;p&gt;You can also specify configuration parameters for &lt;code&gt;electron-builder&lt;/code&gt; in your &lt;code&gt;package.json&lt;/code&gt; file under the &lt;code&gt;&amp;quot;build&amp;quot;&lt;/code&gt; key. I recommend the following options:&lt;/p&gt;

&lt;div class=&#34;file-name&#34;&gt;
	&lt;code&gt;
		package.json
	&lt;/code&gt;
&lt;/div&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
	&lt;span class=&#34;nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;your-app&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
	&lt;span class=&#34;nt&#34;&gt;&amp;#34;build&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;#34;appId&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;com.yourcompany.yourapp&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;#34;productName&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Your App&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;#34;mac&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
			&lt;span class=&#34;nt&#34;&gt;&amp;#34;category&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;public.app-category.lifestyle&amp;#34;&lt;/span&gt;
		&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;#34;dmg&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
			&lt;span class=&#34;nt&#34;&gt;&amp;#34;icon&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;
		&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
		&lt;span class=&#34;nt&#34;&gt;&amp;#34;linux&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
			&lt;span class=&#34;nt&#34;&gt;&amp;#34;target&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;AppImage&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
			&lt;span class=&#34;nt&#34;&gt;&amp;#34;category&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Office&amp;#34;&lt;/span&gt;
		&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;See &lt;a href=&#34;https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/LaunchServicesKeys.html#//apple_ref/doc/uid/TP40009250-SW8&#34;&gt;here&lt;/a&gt; for a list of possible Mac app categories and &lt;a href=&#34;https://specifications.freedesktop.org/menu-spec/latest/apa.html#main-category-registry&#34;&gt;here&lt;/a&gt; for the available Linux categories.&lt;/p&gt;
&lt;p&gt;Finally, create a folder named &lt;code&gt;build&lt;/code&gt; in your project&amp;rsquo;s root directory and copy your app icon (named &lt;code&gt;icon.png&lt;/code&gt;) into it. If you don&amp;rsquo;t add this file, the default Electron icon will be used.&lt;/p&gt;
&lt;p&gt;You can now run &lt;code&gt;yarn build&lt;/code&gt; and your app should get packaged for the platforms you specified earlier. You can find the output in the &lt;code&gt;dist&lt;/code&gt; directory (which you should add to your &lt;code&gt;.gitignore&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s important to know that, by default, &lt;code&gt;electron-builder&lt;/code&gt; will include all dependencies from your &lt;code&gt;package.json&lt;/code&gt; file in the app package, whereas development dependencies are ignored. To keep your app size small, you need to specify dependencies as &lt;code&gt;devDependencies&lt;/code&gt; if your app doesn&amp;rsquo;t use them in production. If you&amp;rsquo;re using a module bundler like Webpack, you should either mark the bundled dependencies as &lt;code&gt;devDependencies&lt;/code&gt; (to avoid having them in your package twice) or configure &lt;code&gt;electron-builder&lt;/code&gt; to skip these dependencies (using the &lt;code&gt;&amp;quot;files&amp;quot;&lt;/code&gt; configuration key).&lt;/p&gt;
&lt;h3 id=&#34;auto-update&#34;&gt;Auto Update&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;electron-builder&lt;/code&gt; comes with built-in support for &lt;code&gt;electron-updater&lt;/code&gt;, which checks your download server for new app versions every time the app is launched. If a more recent version exists, it&amp;rsquo;s automatically downloaded in the background and installed after the user closes the app.&lt;/p&gt;
&lt;p&gt;To use &lt;code&gt;electron-updater&lt;/code&gt; in your project, run the following command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;yarn add electron-updater
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Add the following code to your main process:&lt;/p&gt;

&lt;div class=&#34;file-name&#34;&gt;
	&lt;code&gt;
		main.js
	&lt;/code&gt;
&lt;/div&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;autoUpdater&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;electron-updater&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;nx&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;on&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ready&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
	&lt;span class=&#34;nx&#34;&gt;autoUpdater&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;checkForUpdatesAndNotify&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you&amp;rsquo;re using GitHub Releases for distributing your app (explained later in this guide), that&amp;rsquo;s all the configuration you need for the auto-updater to work!&lt;/p&gt;
&lt;h3 id=&#34;code-signing&#34;&gt;Code Signing&lt;/h3&gt;
&lt;p&gt;For auto-updating to work on macOS, your code needs to be signed:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;To obtain code signing certificates, you need to be enrolled in the &lt;a href=&#34;https://developer.apple.com/programs&#34;&gt;Apple Developer Program&lt;/a&gt; (costs annually).&lt;/li&gt;
&lt;li&gt;Install &lt;a href=&#34;https://developer.apple.com/xcode&#34;&gt;Xcode&lt;/a&gt; if necessary.&lt;/li&gt;
&lt;li&gt;Open Xcode → Preferences → Accounts → Manage Certificates. Add one of each macOS-related certificate. Having one of each type allows for distribution both inside and outside the Mac App Store. The certificates are automatically added to your Keychain, where &lt;code&gt;electron-builder&lt;/code&gt; can detect them. Your code will now automatically be signed whenever you run the &lt;code&gt;build&lt;/code&gt; script.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&#34;https://www.electron.build/code-signing#windows&#34;&gt;Code signing of Windows apps&lt;/a&gt; is optional. If you choose not to sign your app, your users will be presented with a warning when installing your app.&lt;/p&gt;
&lt;h3 id=&#34;release&#34;&gt;Release&lt;/h3&gt;
&lt;h4 id=&#34;manual-release&#34;&gt;Manual Release&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;electron-builder&lt;/code&gt; supports various platforms for storing your app. By default, GitHub Releases will be used to store the files. To be able to publish on GitHub, &lt;a href=&#34;https://github.com/settings/tokens&#34;&gt;generate a Personal Access Token&lt;/a&gt; for &lt;code&gt;electron-builder&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Whenever you want to publish a new version of your app, do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Increase the version number in your &lt;code&gt;package.json&lt;/code&gt; file. Commit and push this change.&lt;/li&gt;
&lt;li&gt;Run the &lt;code&gt;release&lt;/code&gt; script with your GitHub token: &lt;code&gt;GH_TOKEN=... yarn release&lt;/code&gt;. Your app will be built and the packages will be uploaded to GitHub. A release draft for the new version will be created.&lt;/li&gt;
&lt;li&gt;Open the GitHub page of your repository and find the new release draft with the download links for your app. Add a changelog and publish the release.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That&amp;rsquo;s it! Your Electron app is now ready to be downloaded from its GitHub page. If you additionally want to publish your app on the Mac App Store, see &lt;a href=&#34;https://samuelmeuli.com/blog/2019-04-09-publishing-an-electron-app-on-the-mac-app-store/&#34;&gt;this follow-up post&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;using-github-actions&#34;&gt;Using GitHub Actions&lt;/h4&gt;
&lt;p&gt;Instead of building and releasing the app manually, you can also use GitHub Actions to do this task for you. You can read more about this process in &lt;a href=&#34;https://samuelmeuli.com/blog/2019-11-17-automating-the-release-of-electron-apps/&#34;&gt;my other blog post&lt;/a&gt;.&lt;/p&gt;
					]]&gt;
				</content:encoded>
			</item>
		
	</channel>
</rss>
