iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
☁️

Kaggle Competitions: A CI/CD Workflow with GitHub Actions and the Kaggle API

に公開

Introduction

Are you editing Kaggle Notebooks directly in the browser editor?

The browser editor has several inconveniences, such as the inability to use Git for version control, difficulty in checking diffs, and the inability to use your preferred editor (like VSCode).

In this article, I will introduce a workflow that consolidates Notebook code management into GitHub and automatically deploys to Kaggle simply by running git push. You can leverage the entire GitHub ecosystem (Actions, Secrets, version control) for Kaggle competitions.

This workflow is based on what I actually used for the Deep Past Challenge (Akkadian-to-English translation competition).

The Final Workflow

Edit Notebook → git push → GitHub Actions → Upload to Kaggle → Submit in Browser
  1. Edit .ipynb locally or on any device
  2. git add && git commit && git push
  3. gh workflow run kaggle-push.yml -f notebook_dir=deep-past
  4. GitHub Actions uploads the notebook using the Kaggle API
  5. Open the Kaggle Notebook screen in your browser and click "Submit to Competition"

Why Can't It Be Fully Automated?

Initially, I planned to automate the entire process through submission, but due to Kaggle API limitations, Notebook submission for code competitions (CreateCodeSubmission) cannot be executed via API (as of February 2026).

requests.exceptions.HTTPError: 403 Client Error: Forbidden

Error details: Permission 'kernelSessions.get' was denied

Technical Reasons

  • Restriction on permission scopes: kernelSessions.get is a permission for monitoring the execution session state of a notebook, and public API tokens (both legacy and new formats) do not include this scope.
  • Uniqueness of code-submission competitions: Unlike simple CSV file uploads, notebook submission involves re-execution and progress monitoring on the platform, requiring higher control privileges.
  • File submission (competitions submit) is also not allowed: In code competitions, direct CSV uploads are rejected (400 Bad Request).

Verified Combinations

Auth Method CLI Version API Result
Legacy API Key 1.8.4 competition_submit_code 403
New API Token (KGAT_...) 1.8.4 competition_submit_code 403
New API Token (KGAT_...) 2.0.0 competition_submit_code 403
New API Token (KGAT_...) 2.0.0 competitions submit (file) 400

In conclusion, until the API specification is updated, a hybrid operation where you "automate up to code deployment and perform the final submission in the browser" is the most realistic approach.

Directory Structure

kaggle-competitions/
├── .github/workflows/
│   └── kaggle-push.yml        # Automation for pushing to Kaggle
├── deep-past/                  # Create directories per competition
│   ├── kernel-metadata.json
│   └── deep-past-baseline.ipynb
└── KAGGLE_WORKFLOW.md

kernel-metadata.json

{
  "id": "your-username/your-kernel-slug",
  "title": "Your Kernel Title",
  "code_file": "your-notebook.ipynb",
  "language": "python",
  "kernel_type": "notebook",
  "is_private": "true",
  "enable_gpu": "false",
  "enable_internet": "false",
  "dataset_sources": [],
  "competition_sources": ["competition-slug"],
  "kernel_sources": [],
  "model_sources": []
}

Important Points

  • enable_internet: "false": Required for code competitions. If Internet is ON, the notebook will not be eligible for submission.
  • competition_sources: Mounts the competition data. Note the path carefully (explained later).
  • is_private: "true": For submission. Create a separate notebook for public versions aimed at medals.

GitHub Actions Workflow

name: Kaggle Kernels Push

on:
  workflow_dispatch:
    inputs:
      notebook_dir:
        description: 'Notebook directory (e.g., deep-past)'
        required: true
        type: string

jobs:
  push:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Install kaggle CLI
        run: pip install kaggle

      - name: Push notebook to Kaggle
        env:
          KAGGLE_API_TOKEN: ${{ secrets.KAGGLE_API_TOKEN }}
        run: kaggle kernels push -p "${{ inputs.notebook_dir }}"

Setting up GitHub Secrets

Secret Content
KAGGLE_API_TOKEN Obtained via Kaggle Settings → API Tokens → Generate (KGAT_... format)

Common Pitfalls

1. The Data Path Trap

The mount point for competition_sources is:

/kaggle/input/competitions/<competition-slug>/

It is NOT /kaggle/input/<competition-slug>/. The competitions/ subdirectory must be included.

Debugging code:

from pathlib import Path
for item in sorted(Path('/kaggle/input').iterdir()):
    print(f'  {item.name}/')
    for sub in sorted(item.iterdir()):
        print(f'    {sub.name} ({sub.stat().st_size:,} bytes)')

2. Windows Encoding Problem with kernels output

Logs containing non-ASCII characters (like Akkadian) cause cp932 errors with kaggle kernels output. Avoid this by hitting the API directly:

import base64, json, urllib.request, pathlib

creds = json.loads(pathlib.Path.home().joinpath('.kaggle/kaggle.json').read_text())
username = creds['username']
key = creds['key']
auth = base64.b64encode(f'{username}:{key}'.encode()).decode()

url = f'https://www.kaggle.com/api/v1/kernels/output?userName={username}&kernelSlug=your-kernel-slug'
req = urllib.request.Request(url)
req.add_header('Authorization', f'Basic {auth}')

resp = urllib.request.urlopen(req)
outer = json.loads(resp.read().decode('utf-8'))
log = json.loads(outer['logNullable'])

for e in log:
    if e.get('stream_name') == 'stdout':
        print(e['data'], end='')

3. Cannot submit if Internet is ON

If you set enable_internet: "true" in a code competition, the notebook will execute normally but will not be recognized as a valid submission. Make sure to set it to "false".

Operational Flow (Example)

The actual flow for the Deep Past Challenge (Akkadian-to-English translation competition):

  1. Create a baseline Notebook locally (TF-IDF nearest neighbor)
  2. git push → GitHub Actions → Upload to Kaggle
  3. Submit in browser
  4. Baseline submission completed with Public Score: 5.6 (1795th place)

You can perform iterations to improve your score using the same flow.

Summary

Process Automation Method
Notebook editing - Local / Any device
Upload to Kaggle Automated GitHub Actions + kaggle kernels push
Submission Manual "Submit to Competition" in browser
Score check Automated kaggle competitions submissions API

While full automation could not be achieved, because code management and deployment are handled via GitHub, the code is reflected on Kaggle just by running git push from any device.

Only the single click to press the submit button remains manual, but all other processes are completed in the cloud.

GitHubで編集を提案

Discussion