Push to GitHub and Pull Experiments#

This tutorial demonstrates how to push experiments managed by MINTO to GitHub Packages using OMMX Artifact functionality, and how other users can pull these experiments.

OMMX Artifact allows you to push experimental results to other container registries as well. By pushing to GitHub Packages, you can manage both your code and experimental results on GitHub, making it easier to share with your team.

First, let’s conduct numerical experiments for mathematical optimization. Here, we will perform the same numerical experiments as in “Quick Start”. For details, please refer to the original tutorial.

import minto
import ommx_pyscipopt_adapter as scip_ad
from ommx.dataset import miplib2017
instance_name = "reblock115"
instance = miplib2017(instance_name)

timelimit_list = [0.1, 0.5, 1, 2]

experiment = minto.Experiment("scip_reblock115", auto_saving=False)

experiment.log_instance(instance_name, instance)
adapter = scip_ad.OMMXPySCIPOptAdapter(instance)
scip_model = adapter.solver_input

for timelimit in timelimit_list:
    with experiment.run():
        experiment.log_parameter("timelimit", timelimit)

        # Solve by SCIP
        scip_model.setParam("limits/time", timelimit)
        scip_model.optimize()
        solution = adapter.decode(scip_model)

        experiment.log_solution("scip", solution)
experiment.get_run_table()
solution_scip parameter metadata
objective feasible optimality relaxation start name timelimit run_id elapsed_time
run_id
0 0.000000e+00 True 0 0 None scip 0.1 0 0.114259
1 -2.841909e+07 True 0 0 None scip 0.5 1 0.451741
2 -2.841909e+07 True 0 0 None scip 1.0 2 0.512328
3 -2.841909e+07 True 0 0 None scip 2.0 3 1.011504

Pushing Results to GitHub#

Let’s learn how to push your experimental results to GitHub Packages.

Prerequisites#

  1. You’ll need a GitHub account and repository.

  2. If you haven’t created one yet, please refer to the GitHub documentation on creating a repository. You’ll need to configure OMMX Artifact to access GitHub Packages. While detailed instructions can be found in the OMMX Artifact Notebook, we’ll cover the essential setup steps for pushing below.

Pushing to GitHub Packages requires authentication using either a Personal Access Token (PAT) or GITHUB_TOKEN on GitHub Actions. You have two options for authentication:

Authentication Setup#

Pushing to GitHub Packages requires authentication using either a Personal Access Token (PAT) or GITHUB_TOKEN on GitHub Actions. You have two options for authentication:

  1. Using the CLI: Run ommx login to store authentication information locally on your machine

  2. Using Environment Variables:

    • Set the following environment variables:

    env:
        OMMX_BASIC_AUTH_DOMAIN: ghcr.io
        OMMX_BASIC_AUTH_USERNAME: ${{ github.actor }}
        OMMX_BASIC_AUTH_PASSWORD: ${{ github.token }}
    
    • For the OMMX_BASIC_AUTH_PASSWORD, you’ll need to create a GitHub Personal Access Token. Follow the GitHub guide on creating a Personal Access Token, and make sure to enable the write:packages permission.

Note: We use OMMX Artifact functionality for pushing and pulling to/from GitHub Packages. Therefore, GitHub authentication and other settings follow the same configuration as OMMX Artifact. For more details, please refer to this notebook.

Pushing to GitHub Packages#

Once your authentication is set up, you can use the Experiment.push_github method to push to GitHub Packages. The method accepts the following parameters:

  • org: Your GitHub Organization name

  • repo: Your GitHub repository name

  • name: The Artifact name (defaults to Experiment.name)

  • tag: Tag name (defaults to Experiment.timestamp.strftime('%Y%m%d%H%M%S'))

# import os

# If environment variables are not set, please use the following to set them.
# Environment variables
# os.environ["OMMX_BASIC_AUTH_DOMAIN"] = 'ghcr.io'
# os.environ["OMMX_BASIC_AUTH_USERNAME"] = 'xxx'
# os.environ["OMMX_BASIC_AUTH_PASSWORD"] = "xxx"

Let’s try pushing to GitHub Packages using the Experiment.push_github method. As mentioned above, you don’t need to specify the name and tag parameters. The method returns an ommx.Artifact object, and you can check the pushed image name using ommx.Artifact.image_name.

artifact = experiment.push_github(org="Jij-Inc", repo="MINTO-Public")
artifact.image_name
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Cell In[5], line 1
----> 1 artifact = experiment.push_github(org="Jij-Inc", repo="MINTO-Public")
      2 artifact.image_name

File /opt/conda/lib/python3.11/site-packages/minto/experiment.py:551, in Experiment.push_github(self, org, repo, name, tag)
    549 self.dataspace.add_to_artifact_builder(builder)
    550 artifact = builder.build()
--> 551 artifact.push()
    552 return artifact

File /opt/conda/lib/python3.11/site-packages/ommx/artifact.py:158, in Artifact.push(self)
    154 def push(self):
    155     """
    156     Push the artifact to remote registry
    157     """
--> 158     self._base.push()

File /opt/conda/lib/python3.11/site-packages/ommx/artifact.py:100, in ArtifactDir.push(self)
     99 def push(self):
--> 100     self._base.push()

RuntimeError: https://ghcr.io/token?scope=repository%3Ajij-inc%2Fminto-public%2Fscip_reblock115%3Apull&service=ghcr.io: status code 401

Pull from GitHub#

Next, let’s try pulling the image we pushed to GitHub Packages. For this purpose, we use the minto.Experiment.load_from_registry method. This method supports pulling from other Container Registries as well as GitHub Packages. Therefore, you need to specify the image name directly.

exp2 = minto.Experiment.load_from_registry(
    "ghcr.io/jij-inc/minto-public/scip_reblock115:20241223101904"
)
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Cell In[6], line 1
----> 1 exp2 = minto.Experiment.load_from_registry(
      2     "ghcr.io/jij-inc/minto-public/scip_reblock115:20241223101904"
      3 )

File /opt/conda/lib/python3.11/site-packages/minto/experiment.py:576, in Experiment.load_from_registry(cls, imagename)
    566 @classmethod
    567 def load_from_registry(cls, imagename: str) -> "Experiment":
    568     """Load an experiment from a Docker registry.
    569 
    570     Args:
   (...)
    574         Experiment: Instance of the loaded experiment.
    575     """
--> 576     artifact = ox_artifact.Artifact.load(imagename)
    577     dataspace = ExperimentDataSpace.load_from_ommx_artifact(artifact)
    578     exp_name = dataspace.experiment_datastore.meta_data["experiment_name"]

File /opt/conda/lib/python3.11/site-packages/ommx/artifact.py:151, in Artifact.load(image_name)
    136 @staticmethod
    137 def load(image_name: str) -> Artifact:
    138     """
    139     Load an artifact stored as container image in local or remote registry
    140 
   (...)
    149 
    150     """
--> 151     base = ArtifactDir.from_image_name(image_name)
    152     return Artifact(base)

File /opt/conda/lib/python3.11/site-packages/ommx/artifact.py:82, in ArtifactDir.from_image_name(image_name)
     80 @staticmethod
     81 def from_image_name(image_name: str) -> ArtifactDir:
---> 82     return ArtifactDir(_ArtifactDir.from_image_name(image_name))

RuntimeError: https://ghcr.io/token?scope=repository%3Ajij-inc%2Fminto-public%2Fscip_reblock115%3Apull&service=ghcr.io: status code 401
exp2.get_run_table()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[7], line 1
----> 1 exp2.get_run_table()

NameError: name 'exp2' is not defined

We have introduced how to push and pull to/from GitHub Packages. This method makes it easier to manage experimental results with MINTO on GitHub and share them with your team.