This documents common maintenance tasks for this codebase, to make ongoing maintenance less dependent on any single individual.
Release a new version using the Release workflow.
- Click "Run workflow"
- Select a branch to release from
- Specify a version number (based on our versioning policy)
- Click "Run workflow"
Tip
A "Dry Run" option is also available. It's primarily intended for use when testing changes to the Release workflow. It does the release actions which are reversible (e.g. bumping the version, pushing a branch, opening a PR, generating draft release notes) while skipping the one action that's not reversible (actually releasing to rubygems.org). When used, please remember to cleanup afterwards: close the PR and delete the draft release notes.
Important
If there's any question about the readiness to release a new version to end users, please release a release candidate
using a version number like 1.2.0.rc1, 1.2.0.rc2, etc. After the release candidate has been thorougly tested, we
can cut the final release.
After the workflow completes, review the PR that gets opened (example) and follow its checklist. The release notes can be authored after cutting a release if needed (but it's nice to have them ready to go if possible).
A Claude Code skill is available to help draft release notes:
# Generate notes from most recent release to HEAD
/release-notes 1.1.0
# Generate notes from a specific version
/release-notes 1.1.0 --from 1.0.2The skill gathers all PRs, categorizes them, identifies new contributors, and drafts release notes following the structure below. Review and refine the output as needed.
Release notes should follow this general structure:
ElasticGraph vX.Y.Z has been released! This release includes...
## New Features
Describe major new features here with a subheading dedicated to each.
## Upgrade notes
Describe how to upgrade ElasticGraph from the prior version.
## What's Changed
<In this section we provide bullet-point lists linking to each PR, but we often combine many PRs into a single bullet point.>
### New Features
...
### Breaking Changes
...
### Performance Optimizations
...
### Bug Fixes
...
### Other Improvements
...
### Dependency Upgrades
The datastore versions we build against have been upgraded:
...
The following Ruby gems have been upgraded:
...
The following GitHub actions have been upgraded:
...
The following NPM packages have been upgraded:
...
The following Python packages have been upgraded:
...
## New Contributors
* List new contributors here; the auto generated release notes provide this
**Full Changelog**: <GitHub compare URL provided by autogenerated release notes>Important
We're threading the needle here between acknowledging every contribution (we want to acknowledge contributors!) and keeping the release notes at an appropriate level of detail for our user base. Users generally don't care about internal improvements to the ElasticGraph codebase that have zero impact on the experience of using ElasticGraph. That's why we often combine many PRs into a single bullet point like "Various other codebase maintenance tasks".
Note
For a pre-release (e.g. X.Y.Z.rc1), we generally don't bother writing up release notes, since it takes effort and we don't expect users
to use pre-releases. Instead, we just use the autogenerated release notes provided by GitHub.
Later, when releasing the final version (e.g. X.Y.Z), be sure to include everything, including things that were actually released in
the release candidate.
For a good example of release notes, see the v0.19.2.0 release notes.
We want ElasticGraph to stay up-to-date with the latest Elasticsearch/OpenSearch versions. We don't bother keeping up to date with every patch release, but do want to stay current with the latest major/minor releases. However, we always opt for the most recent patch release when upgrading.
In addition, we don't want to bloat our CI build by building against every supported Elasticsearch/OpenSearch version. Instead, we cover a range of versions by building against a minimum version and a maximum version.
- Find Elasticsearch releases on the Elastic.co docker page
- Find OpenSearch releases on the Docker Hub page
To upgrade a version, update the versions in elasticgraph-local/lib/elastic_graph/local/tested_datastore_versions.yaml. Then run:
script/update_ci_yamlSee #545 for an example PR.
ElasticGraph maintains a set of valid time zones,
which is used to validate client-provided values for the TimeZone scalar type. The set is maintained and validated in a few ways:
- elasticgraph-graphql/script/dump_time_zones
generates
valid_time_zones.rbby querying the JVM (in order to match OpenSearch and Elasticsearch since they run on the JVM). - A unit test
verifies that
valid_time_zones.rbis up-to-date. - An acceptance test
executes a GraphQL query using every time zone, to verify that all time zones accepted by our
TimeZonescalar type are in fact handled by our supported Elasticsearch and OpenSearch versions.
The folks who maintain the tzdata database occasionally add new time zones to the database. After that happens, the aforementioned unit test
may begin to fail (e.g. once the updated tzdata file has landed on the GitHub actions workers...). Initially, we can just ignore/exclude
the new time zone (given that old OpenSearch and Elasticsearch docker images bundle a tzdata file that lacks it). See this
PR for an example. Once it's handled by all supported datastore versions, we can stop
ignoring it.
We use Dependabot to automatically keep dependencies up-to-date. Our dependabot config configures the cadence of dependabot updates (among other things)--feel free to tweak it as needed.
We have some custom tooling that hooks into Dependabot PRs and updates some other artifacts:
- script/update_gem_constraints updates constraints in our
gemspecs. Dependabot only updates the version in
Gemfile/Gemfile.lock, leaving our gemspec constraints untouched. However, it helps avoid surprises for ElasticGraph users if they get the same gem versions our CI runs against, so we want the constraints in our gemspecs to be updated to match. - workflows/update-gem-version-artifacts.yaml
runs on Dependabot PRs. It runs
script/update_gem_constraints, updates rbs_collection.lock.yaml, and pushes a commit to the PR.
Dependabot PRs can be reviewed and merged without the approval of another maintainer. Before merging, please:
- Review the release notes provided by Dependabot in the PR description. If there are any new features of a dependency that we should take advantage of, please open an issue so we can track that work.
- Confirm the CI build fully passes. If the build has a non-transient failure and the PR is upgrading multiple dependencies, consider updating .github/dependabot.yml to exclude the culprit from inclusion in a multiple-dependency PR. (It's nice to isolate such a dependency into its own PR.)
- Review the diff to make sure it looks reasonable.
When merging, please use the "Squash and merge" option as we don't need to keep the two commits in the PR separate. If a Dependabot PR
has merge conflicts, comment on the PR with @dependabot recreate rather than @dependabot rebase so that the updates from
script/update_gem_constraints get recreated as well.
Dependabot is configured to run on a regular cadence, but if you ever need to trigger it by hand (e.g. to troubleshoot a problem with it), you can do so from the Dependency Graph--Dependabot page:
- Click "Recent update jobs" next to a dependabot job
- Click the "Check for updates" button
The GraphiQL UI served by elasticgraph-graphiql uses locally vendored assets, packaged into elasticgraph-graphiql/lib/elastic_graph/graphiql/assets.tar.gz.
These assets are built from a specified version of the official graphql/graphiql Vite example (examples/graphiql-vite).
This ensures the UI can run offline, is not dependent on external CDNs, and uses ElasticGraph project favicons.
The elasticgraph-graphiql/lib/elastic_graph/graphiql.rb application extracts this tarball into a temporary directory at runtime to serve the UI.
To update the graphiql.tar.gz archive (e.g., to a newer version of GraphiQL or to reflect changes in project favicons):
-
Prerequisites: Ensure you have the following command-line tools installed and available in your system's PATH:
gitnode(Node.js, a recent LTS version is recommended)yarn(Yarn package manager)targzip(usually included withtar)
-
Run the Update Script: Execute the following script from the root of the
elasticgraph-fully-local-graphiqlproject. You can optionally specify a git ref (tag, branch, or commit SHA) from thegraphql/graphiqlrepository using the--refoption.# To use a specific version, e.g., a tag graphiql@5.0.3 elasticgraph-graphiql/script/update_graphiql --ref graphiql@5.0.3 -
What the Script Does:
- Clones the specified version of the
graphql/graphiqlrepository into a temporary directory. - Modifies the source of the
examples/graphiql-vite(App.jsx) to use/graphqlas its API endpoint. - Installs all necessary Node.js dependencies for the monorepo using
yarn install. - Builds all packages within the
graphql/graphiqlmonorepo usingyarn build. - Builds the specific
example-graphiql-viteworkspace usingyarn workspace example-graphiql-vite build. - Modifies the resulting
dist/index.htmlto set the title to "ElasticGraph GraphiQL". - Copies favicons from this project's
config/site/src/assets/favicons/into thedist/directory. - Creates a
graphiql.tar.gzarchive from the contents of the modifieddist/directory. - Saves this archive to
elasticgraph-graphiql/lib/elastic_graph/graphiql/assets.tar.gz. - Cleans up the temporary build directory.
- Clones the specified version of the
-
Test the updated GraphiQL:
- Boot locally with
bundle exec rake boot_locally. - Try out the GraphiQL UI in the browser to confirm it works.
- Confirm in the network tab that all assets load correctly.
- Boot locally with
-
Commit Changes: After the script successfully completes, the
elasticgraph-graphiql/lib/elastic_graph/graphiql/assets.tar.gzfile will be updated. Review this change and commit it to your version control system.
This process ensures that elasticgraph-graphiql serves a self-contained and consistently branded version of the GraphiQL UI.
Occasionally, it's useful to create a new gem that's part of the set of ElasticGraph gems provided by this repo. Here's how to do that.
- Copy a skeleton from another gem. (
elasticgraph-opensearchis a pretty small one, so it's what we'll use here). Be sure to usecp -Rso that symlinked files copy properly:
cp -R elasticgraph-opensearch elasticgraph-newgem- Cleanup the
lib/spec/sigfiles that were originally inelasticgraph-opensearch(these will be entirely different for your new gem):
rm -rf elasticgraph-newgem/lib/elastic_graph/opensearch
rm -rf elasticgraph-newgem/spec/unit/elastic_graph/opensearch
rm -rf elasticgraph-newgem/sig/elastic_graph/opensearch
rm -rf elasticgraph-newgem/sig/opensearch.rbs-
Use your IDE or similar tool to find and replace
elasticgraph-opensearchwithelasticgraph-newgemin your gem directory. -
Edit the gemspec. Be sure to update the following as needed:
namesummarymetadata.gem_categoryadd_dependencyadd_development_dependency
-
Add the gem to git, and then update our dependency diagrams:
git add elasticgraph-newgem
script/update_dependency_diagrams- Write the code, specs and type signatures for the gem. To run the gem's test suite in the way it's run on CI, run:
script/run_gem_specs elasticgraph-newgem-
Update
rbs_collection.yamlto list the new gem and ignore its type signatures provided by bundler (as they are already available locally in this repo). -
Open a PR with the new gem once it's ready for review.
-
Once that has merged, register the new gem with rubygems.org. We use RubyGems trusted publishing to publish our gems to rubygems.org from a GitHub action. Follow the guide for pushing a new gem. Enter the following details into the "New Pending Trusted Publisher" form:
- RubyGem name: Whatever the new gem is called (elasticgraph-newgem in the examples above)
- Trusted publisher type: GitHub Actions
- Repository owner: block
- Repository name: elasticgraph
- Workflow filename: release.yaml
- Environment: rubygems.org
-
Publish an ElasticGraph release to verify the new gem can be released successfully. This needs to happen within 12 hours of creating the pending trusted publisher on rubygems.org (as that's how long a new pending trusted publisher is valid for). Use the release process explained at the top of this document, but be sure to use a release candidate version (e.g.
1.2.3.rc1). We don't want to be trying out the publishing of a new gem for the first time when cutting a final release.
The project has a root README and a README within each gem directory. Much of the content of the READMEs is generated or validated to ensure accurate documentation.
- The
mermaiddependency diagrams are automatically generated byscript/update_dependency_diagrams. CI checks them withscript/update_dependency_diagrams --verify. - All other README code snippets are validated by
script/validate_readme_snippets. Here's how that validation works:- A new ElasticGraph project is bootstrapped into
tmp/example_project_for_snippet_validation. bashsnippets are executed from that project directory.diffsnippets are applied to that project directory. Thenbundle exec rakeis executed to confirm the build still passes.rubysnippets are dumped into a file (either at a temp path, or at the path identified in a comment) and then executed.yamlsnippets are parsed as YAML.textsnippets (that is, snippets which don't indicate a type) are not validated. (So a simple way to get the build to pass for a failing snippet is to remove the type, so that it's just text).
- A new ElasticGraph project is bootstrapped into
When updating a README file, you may want to run the validator locally:
script/validate_readme_snippets --file elasticgraph-somegem/README.mdelasticgraph-apollo uses https://github.com/apollographql/apollo-federation-subgraph-compatibility
to verify compatibility with Apollo. Things to note:
- Run
elasticgraph-apollo/script/test_compatibilityto run the compatibility tests (the CI build runs this). - Run
elasticgraph-apollo/script/boot_eg_apollo_implementationto boot the ElasticGraph compatibility test implementation (can be useful for debuggingtest_compatibilityfailures). - These scripts require some additional dependencies to be installed (such as
docker,node, andnpm). - To get that to pass locally on a Mac, I had to enable the
Use Docker Compose V2flag in Docker Desktop (under "Preferences -> General"). Without that checked, I got errors like this:
ERROR: for apollo-federation-subgraph-compatibility_router_1 Cannot start service router: OCI runtime create failed: container_linux.go:380: starting container process caused: process_linux.go:545: container init caused: rootfs_linux.go:76: mounting "/host_mnt/Users/myron/Development/sq-elasticgraph-ruby/elasticgraph-apollo/vendor/apollo-federation-subgraph-compatibility/supergraph.graphql" to rootfs at "/etc/config/supergraph.graphql" caused: mount through procfd: not a directory: unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type