DEV Community

Cover image for πŸ‘©β€πŸ”§ How to Check License Compatibility in GHA
Peter H. Boling
Peter H. Boling

Posted on • Edited on

πŸ‘©β€πŸ”§ How to Check License Compatibility in GHA

Other posts in my Compatibility Matrix Series

You have a project made out of code, sprinkles, and spice, and you want to validate compatibility between your project's license and the licenses of its dependencies, as defined by:

  • Apache Software Foundation (ASF) Categorizations via apache.org
  • Free Software Foundation's (FSF) Free/Libre designations via spdx.org
  • Open Source Initiative (OSI) Approved designations via spdx.org
  • Any of the above

What is Compatible?

Apache Software Foundation

IANAL, but Apache Software Foundation has resolved many legal issues between licenses and determined their compatibility to my satisfaction. Take it up with them if your fractious children want to quarrel about it.

  • Category A licenses are compatible with each other and with Apache Software Foundation projects generally.
  • Category B licenses are compatible with each other, and with Apache Software Foundation projects when included as binary code.
  • Other licenses need manual validation, and compatibility can be configured and documented per project.

These categorizations are the backbone of the license checker, see further down for a configuration example.

FSF Free/Libre

Supported. In your licenserc.yaml:

dependency:
  require_fsf_free: true # will only consider compatible if license is FSF Free/Libre; default false
Enter fullscreen mode Exit fullscreen mode

OSI Approved

Supported. In your licenserc.yaml:

dependency:
  require_osi_approved: true # will only consider compatible if license is OSI Approved; default false
Enter fullscreen mode Exit fullscreen mode

How can we check compatibility?

I've now pushed many PRs to a project called Apache SkyWalking Eyes (#205, #207, #208, #209, ... #247, #248, #249, #250). And now it is ready to write about.

It works for a basic use case of a project with MIT and Ruby licensed dependencies, such as oauth2:
https://github.com/ruby-oauth/oauth2/pull/676

It also works for more complex use cases with many dependencies across a broad set of open source licenses.

Project Setup

This example will use a Ruby project as an example, but there is support for Create two files:

# .licenserc.yaml

header:
  license:
    spdx-id: MIT # The license of your project!

dependency:
  require_fsf_free: false # if "FSF Free/Libre" is required, set to true
  require_osi_approved: false # if "OSI Approved" is required, set to true
  files:
    - Gemfile.lock      # If this is a Ruby project (Bundler). Ensure Gemfile.lock is committed.
    # - pom.xml           # If this is a maven project.
    # - Cargo.toml        # If this is a rust project.
    # - package.json      # If this is a npm project.
    # - go.mod            # If this is a Go project.
Enter fullscreen mode Exit fullscreen mode

and

# .github/workflows/license-eye.yml

name: Apache SkyWalking Eyes

permissions:
  contents: read

on:
  push:
    branches:
      - 'main'
      - '*-stable'
    tags:
      - '!*' # Do not execute on tags
  pull_request:
    branches:
      - '*'
  # Allow manually triggering the workflow.
  workflow_dispatch:

# Cancels all previous workflow runs for the same branch that have not yet completed.
concurrency:
  # The concurrency group contains the workflow name and the branch name.
  group: "${{ github.workflow }}-${{ github.ref }}"
  cancel-in-progress: true

jobs:
  license-check:
    if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')"
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v5

      - name: Check Dependencies' License
        uses: apache/skywalking-eyes/dependency@main
        with:
          config: .licenserc.yaml
          # Ruby packages declared as dependencies in gemspecs or Gemfiles are
          #   typically consumed as binaries; enable weak-compatibility
          #   so permissive and weak-copyleft combinations are treated as compatible.
          flags: --weak-compatible

Enter fullscreen mode Exit fullscreen mode

Result

End result workflow runs look like:
https://github.com/ruby-oauth/oauth2/actions/workflows/license-eye.yml

Experiment: if we mark the Ruby license (which is category B) as incompatible in our MIT (category A) projects, this is what would happen:

Cool, right? I'm not suggesting you do that, since in Ruby dependencies are normally included as binaries, so Category B is generally compatible with Category A licenses in Ruby projects...

Projects that declare no license are problematic and will fail in this same way, alerting you to the problem.

You'll also get notified if downstream dependencies change their licenses to something incompatible.

Spread Awareness

Because licenses matter...

Now is a good time to make your community of users aware of your shiny license compliance via README.md badges...

Apache SkyWalking Eyes License Compatibility Check
Compatible with Apache Software Projects: Verified by SkyWalking Eyes

[![Apache SkyWalking Eyes License Compatibility Check][🚎15-πŸͺͺ-wfi]][🚎15-πŸͺͺ-wf]
[![Compatible with Apache Software Projects: Verified by SkyWalking Eyes][πŸ“„license-compat-img]][πŸ“„license-compat]

[🚎15-πŸͺͺ-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/license-eye.yml
[🚎15-πŸͺͺ-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/license-eye.yml/badge.svg
[πŸ“„license-compat]: https://www.apache.org/legal/resolved.html#category-a
[πŸ“„license-compat-img]: https://img.shields.io/badge/Apache_Compatible:_Category_A-βœ“-259D6C.svg?style=flat&logo=Apache
[πŸ“„license-compat-img-raster]: https://raster.shields.io/badge/Apache_Compatible:_Category_A-βœ“-259D6C.png?style=flat&logo=Apache
# note: dev.to will only render the PNG rasterized version;
#       in READMEs you should use the SVG for better image clarity.
Enter fullscreen mode Exit fullscreen mode

Support & Funding Info

I am a full-time FLOSS maintainer. If you find my work valuable, I ask that you become a sponsor. Every dollar helps!

πŸ₯° Support FLOSS work πŸ₯° Get access "Sponsors" channel on Galtzo FLOSS Discord πŸ‘‡οΈ Live Chat on Discord
OpenCollective Backers OpenCollective Sponsors Buy me a coffee Donate at ko-fi.com Donate on PayPal Donate on Polar Sponsor Me on Github Liberapay Goal Progress

Photo (cropped) by Zoha Gohar on Unsplash

Top comments (3)

Collapse
 
averiai profile image
Averi AI

Good post!

Collapse
 
galtzo profile image
Peter H. Boling

Thanks! You can see it in action here:
github.com/ruby-oauth/oauth2/actio...

Collapse
 
alia_noza_2ca70e5b73f0382 profile image
Alia Noza

Great post! Very helpful.