Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(ci): Automate Docker image publication when merging on master #1142

Merged
merged 4 commits into from
Oct 20, 2023

Conversation

pixelastic
Copy link
Collaborator

@pixelastic pixelastic commented Oct 19, 2023

This PR adds a second workflow, publish, to the existing GitHub Actions workflow.

This one will be triggered on every commit on master (so, on every PR merge, as master is protected). It will then:

  • Run the validate workflow again, just to be sure we don't have any Lint/Build/Test issues
  • Check if we should publish a new version by checking the git commit history for any BREAKING CHANGE / feat() or fix()
  • If no new version needs to be published, the build will just stop (but still marked as a success)
  • If a new version needs to be published, it will increase the version in package.json (major, minor or patch, depending on the type of commit), and update CHANGELOG.md with the list of changes.
  • A new commit will be added to the repo with those two changes, and tagged with the version number
  • The code source will be added to GitHub Releases (not very useful, I don't think we use it, but I left it as it was that way before)
  • A Docker image will be built and pushed to GitHub Packages (ghcr.io registry)

image

The bulk of the job is done by the semantic-release package, but I had to add a few tweaks:

I made the previous validate workflow re-usable, to avoid code duplication. There is still some code duplication to checkout, install node and its dependencies, but I don't think we can shave it more.

I added a yarn publish:check script that simply checks if a new version should be released (by checking the commit history). The exit code of that script is then used in the workflow to conditionally continue the publication or not, but still keep the workflow as a success even if there is no publish to do.

I cleaned up the release.config.js file to make our intent more explicit. It was previously relying on a lot of default values and only overriding the ones we weren't interested in. I reversed it and explictly define the one we want. Hopefully the workflow will be easier to understand.

semantic-release doesn't have a way to do GitHub Packages publications, so I created the yarn publish:docker for that. It builds the image (with the requires tags and labels), login to ghcr.io (thankfully, GitHub Actions provides a one-time-use GITHUB_TOKEN with all the required permission on each run), and push the new image (with the specific version and overriding the latest tag)

Note: I specifically named the PR commit with feat() so once merged on master it should trigger a new release. I did test the workflow as much as I could on my branch in dry run mode, but the real test will be once this PR gets merged.

@pixelastic
Copy link
Collaborator Author

I removed CircleCI configuration in this PR, but CircleCI checks are still running because the configuration is still present on master. CircleCI checks should completely disappear once this PR is merged.

We have another mention of CircleCI in jest.config.js, but I don't know its purpose:

 // reporter for circleci
  reporters: [
    'default',
    [
      'jest-junit',
      {
        outputDirectory: 'junit',
        suiteNameTemplate: '{filepath}',
        ancestorSeparator: ' › ',
        addFileAttribute: 'true',
      },
    ],
  ],

https://github.com/algolia/npm-search/blob/master/jest.config.js#L20-L31

@Haroenv
Copy link
Collaborator

Haroenv commented Oct 20, 2023

^ that part of the jest config is so that circleCI shows which tests pass, which ones fail etc. GitHub Actions doesn't have that feature

},
// Redirect output to new streams, to make the script silent
{
stdout: new WritableStreamBuffer(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

as we're not using them, I wonder if a builtin writable stream works too? no big deal though, but could avoid the dependency

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm not familiar enough with streams to have found a builtin writable one. I went with the same dependency as the one actually used in semantic-release. Any pointer on what I could try to use?

Copy link
Collaborator

Choose a reason for hiding this comment

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

can be done with:

import {Writable} from 'node:stream'
new Writable({write(_chunk, _encoding, callback) { setImmediate(callback) }})

(but obviously this dep is also fine)

"docker:build": "./scripts/build.sh",
"docker:release": "VERSION=$(node -e \"console.log(require('./package.json').version)\") && echo \"Releasing $VERSION\" && docker push algolia/npm-search && docker push algolia/npm-search:$VERSION"
"publish:check": "node ./scripts/publish-check.js",
"publish:github": "./scripts/publish-github",
Copy link
Collaborator

Choose a reason for hiding this comment

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

this could just be:

Suggested change
"publish:github": "./scripts/publish-github",
"publish:github": "semantic-release",

and the file removed

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Right. I initially had the external script because there was a bit more code before and after, but you're right that it can now be simplified

@pixelastic
Copy link
Collaborator Author

@Haroenv I removed the stream dependency and the CircleCI-specific jest configuration. I kept the external script for publish:github as it contains documentation about what the script does, that I found lacking when I came to the project and had to understand what it was actually doing.

@pixelastic pixelastic merged commit f0208ba into master Oct 20, 2023
3 checks passed
@pixelastic pixelastic deleted the actions/publish branch October 20, 2023 13:10
@pixelastic
Copy link
Collaborator Author

FYI, the build on master failed with remote: error: Required status check "ci/circleci: build" is expected. when attempting to publish.

I assume this is an artefact of me removing CircleCI configuration on that PR, but it still technically being there when attempting to merge

@pixelastic
Copy link
Collaborator Author

image

I updated the repo settings about branch protection. The previous CircleCI build job was explicitly set as a mandatory condition for the protected branch. Commits had to come from a branch where this check was green (which wasn't the case on this PR as I had disabled the whole of CircleCI). I moved it to the new GitHub Actions Validate job.

I might need to do another debug PR to trigger it again

github-actions bot pushed a commit that referenced this pull request Oct 20, 2023
# [1.8.0](v1.7.15...v1.8.0) (2023-10-20)

### Bug Fixes

* **ci:** Trigger CI checks on branch push, not only on PR creation ([#1143](#1143)) ([9d99aa3](9d99aa3))

### Features

* **ci:** Automate Docker image publication when merging on master ([#1142](#1142)) ([f0208ba](f0208ba))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants