Skip to content
Merged

Dev #21

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/commands/fix-lint.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ Fix all lint errors in the project.
1. Run `uv run poe lint` again to check remaining issues
1. Manually fix any issues Ruff couldn't auto-fix
1. Run `uv run poe typecheck` to verify no type errors introduced
1. Run `uv run poe test` to verify fixes didn't break anything
1. Run `uv run poe check-all` to verify fixes didn't break anything

Report what was fixed and what remains (if anything).
8 changes: 7 additions & 1 deletion .claude/commands/release.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Release

Release is fully automated via **release-please**. Claude's role is to verify readiness and monitor the pipeline — never to create tags, bump versions manually, or trigger workflows directly.
Release is intended to be automated via **release-please** (not yet configured). Claude's role is to verify readiness and monitor the pipeline — never to create tags, bump versions manually, or trigger workflows directly.

## How it works

Expand All @@ -22,6 +22,12 @@ conventional commits merged to main

1. **Verify release-please app triggered**

```bash
gh run list --workflow=reusable-release-please.yml --limit 5
```

1. **Check for open Release PR**

```bash
gh pr list --label "autorelease: pending" --limit 5
```
Expand Down
2 changes: 1 addition & 1 deletion .claude/commands/validate.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Run the full validation pipeline for the current repo. Stop and report on first
1. **Tests**

```bash
uv run poe test
uv run poe check-all
# fallback: uv run pytest tests/ -x --tb=short -q
```

Expand Down
2 changes: 1 addition & 1 deletion .claude/memory/long-term-memory.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,5 @@ _Nothing yet._

- **Source:** <https://github.com/astral-sh/uv/releases>
- **Finding:** uv 0.10.8 switches default binary/CPython mirror from python.org to Astral mirrors. Raw `curl | sh` uv installs in CI are unpinned.
- **Impact:** Replaced `curl -LsSf https://astral.sh/uv/install.sh | sh` with `astral-sh/setup-uv@v4` in `.github/workflows/ci.yml` (both jobs).
- **Impact:** Replaced `curl -LsSf https://astral.sh/uv/install.sh | sh` with `astral-sh/setup-uv@v7` in `.github/workflows/ci.yml` (both jobs) and `.github/workflows/package-validation.yml`. Note: these workflows were removed in the 2026-07-16 `.github` cleanup; the UV setup pattern now lives in individual repos (`dataenginex`, `dex-studio`).
- **Status:** fixed — 2026-03-19
25 changes: 25 additions & 0 deletions .claude/memory/project-memory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Project Memory (active state)

> Tracks in-flight work, open decisions, and cross-repo state.
> Updated by consolidate-memory skill nightly.
> Facts here are ephemeral — they get promoted or dropped, never age indefinitely.

## Active Tasks & In-Flight Work

_Nothing yet._

## Open Decisions (unresolved)

_Nothing yet._

## Cross-Repo State

| Repo | Status | Last Known Action |
|------|--------|------------------|
| dataenginex (dex) | — | — |
| dex-studio | — | — |
| infradex | — | — |

## Blockers

_None._
60 changes: 60 additions & 0 deletions .github/workflows/WORKFLOWS_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# GitHub Actions Workflows

CI/CD automation for the DataEngineX `.github` meta-repo.
Reusable workflows shared across all repos are also in this directory (prefixed `reusable-`).

## Workflows (run in `.github`)

### `security.yml` — Security Scans
**Triggers**: Push/PR to `main`/`dev`

Runs Trivy (misconfig + secret scan). CodeQL is handled by GitHub's default setup.

### `sync-labels.yml` — Label Synchronization
**Triggers**: Push to `main` on `labels.yml` changes, manual dispatch

Syncs labels from `labels.yml` to all repos (dataenginex, dex-studio, infradex).

### `project-automation.yml` — Project Intake Automation
**Triggers**: Issue/PR opened/reopened events, manual dispatch

Adds new issues/PRs to org project board. Requires `ORG_PROJECT_URL` variable + `ORG_PROJECT_TOKEN` secret.

### `stale-issues.yml` — Stale Issue Management
**Triggers**: Scheduled (daily at 6 AM UTC)

Marks issues/PRs stale after 60 days, closes after 30 more.

## Reusable Workflows (called by other repos)

| Workflow | Callers | Purpose |
|----------|---------|---------|
| `reusable-security.yml` | dataenginex, dex-studio, infradex | Trivy scan + Slack notifications |
| `reusable-auto-pr-to-main.yml` | dataenginex, dex-studio | Auto-create PR from feature/fix → main |
| `reusable-auto-pr-to-dev.yml` | (available) | Auto-create PR from feature/fix → dev + auto-merge |
| `reusable-auto-pr-dev-to-main.yml` | (available) | Auto-create PR from dev → main |
| `reusable-enforce-dev-to-main.yml` | (available) | Verify PRs to main come from dev |
| `reusable-claude.yml` | (available) | Claude Code action for @claude mentions |
| `reusable-release-please.yml` | (available) | Release please automation |

## Quick Reference

```bash
# Check CI status
gh pr checks <pr-number>

# View workflow runs
gh run list --workflow security.yml

# Trigger manual label sync
gh workflow run sync-labels.yml
```

## Required Secrets

| Secret | Used by |
|--------|---------|
| `GITHUB_TOKEN` | Auto-provided |
| `ORG_PROJECT_TOKEN` | project-automation.yml |
| `LABELS_SYNC_TOKEN` | sync-labels.yml |
| `SLACK_WEBHOOK` | security.yml (optional) |
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ jobs:
markdownlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- uses: DavidAnson/markdownlint-cli2-action@v19
with:
globs: "**/*.md"
config: ".github/.markdownlint-cli2.jsonc"
config: ".markdownlint-cli2.jsonc"

linkcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- uses: lycheeverse/lychee-action@v2
with:
fail: true
Expand Down
49 changes: 49 additions & 0 deletions .github/workflows/project-automation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Project Automation

on:
issues:
types:
- opened
- reopened
- transferred
pull_request:
types:
- opened
- reopened
- ready_for_review
workflow_dispatch:

permissions:
contents: read
issues: write
pull-requests: write

jobs:
add-to-org-project:
name: Add item to organization project
runs-on: ubuntu-latest
env:
ORG_PROJECT_URL: ${{ vars.ORG_PROJECT_URL }}
ORG_PROJECT_TOKEN: ${{ secrets.ORG_PROJECT_TOKEN }}

steps:
- name: Add issue/PR to organization project
if: ${{ env.ORG_PROJECT_URL != '' && env.ORG_PROJECT_TOKEN != '' }}
id: add_to_project
continue-on-error: true
uses: actions/add-to-project@v1.0.2
with:
project-url: ${{ env.ORG_PROJECT_URL }}
github-token: ${{ env.ORG_PROJECT_TOKEN }}

- name: Explain action failure
if: ${{ steps.add_to_project.outcome == 'failure' }}
run: |
echo "Project automation failed but is non-blocking."
echo "Check ORG_PROJECT_URL and ORG_PROJECT_TOKEN scopes/permissions."

- name: Explain skipped automation
if: ${{ env.ORG_PROJECT_URL == '' || env.ORG_PROJECT_TOKEN == '' }}
run: |
echo "Project automation skipped."
echo "Set repository/org variable ORG_PROJECT_URL and secret ORG_PROJECT_TOKEN to enable."
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Auto PR — branch → main (reusable)
name: Auto PR — dev → main (reusable)

on:
workflow_call:
Expand All @@ -12,42 +12,37 @@ jobs:
pull-requests: write

steps:
- name: Create or update PR
- name: Create or update PR (dev → main)
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
HEAD: ${{ github.ref_name }}
run: |
if echo "$HEAD" | grep -qE '^fix[-/]'; then
TITLE="fix: $(echo "$HEAD" | sed 's|^fix[-/]||;s|-| |g')"
elif echo "$HEAD" | grep -qE '^feat[-/]'; then
TITLE="feat: $(echo "$HEAD" | sed 's|^feat[-/]||;s|-| |g')"
else
TITLE="feat: $(echo "$HEAD" | sed 's|-| |g')"
AHEAD=$(gh api "repos/$GH_REPO/compare/main...dev" --jq '.ahead_by')
if [ "$AHEAD" = "0" ]; then
echo "dev is already in sync with main — nothing to do"
exit 0
fi

echo "PR title: $TITLE"
echo "dev is $AHEAD commit(s) ahead of main"

PR_NUMBER=$(gh pr list \
--base main \
--head "$HEAD" \
--head dev \
--state open \
--json number \
--jq '.[0].number')

if [ -n "$PR_NUMBER" ]; then
echo "PR #$PR_NUMBER already exists"
else
BODY="Automated PR: ${HEAD} → main. Review the preview environment before merging."
gh pr create \
--base main \
--head "$HEAD" \
--title "$TITLE" \
--body "$BODY"
--head dev \
--title "chore: sync dev -> main" \
--body "Automated PR: dev → main. Merge when all required checks pass."

PR_NUMBER=$(gh pr list \
--base main \
--head "$HEAD" \
--head dev \
--state open \
--json number \
--jq '.[0].number')
Expand Down
77 changes: 77 additions & 0 deletions .github/workflows/reusable-auto-pr-to-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Reusable workflow — auto-creates a PR from a feature/fix branch → dev and enables
# auto-merge. The squash commit title is derived from the branch name in conventional
# commit format (feature/feat-add-foo → "feat: add foo").
#
# Prerequisites (one-time per repo, GitHub UI):
# 1. Settings → General → Allow auto-merge ✓
# 2. Settings → Branches → branch protection on 'dev':
# - Require status checks: CI (lint-and-test)
# - Require branches to be up to date before merging

name: Auto PR — feature → dev (reusable)

on:
workflow_call:

jobs:
create-pr:
name: Create PR to dev
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write

steps:
- name: Create or update PR (feature/fix → dev)
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
HEAD: ${{ github.ref_name }}
run: |
# Derive conventional commit title from branch name
# feature/feat-add-pipeline → "feat: add pipeline"
# feature/add-pipeline → "feat: add pipeline"
# fix/fix-null-ptr → "fix: null ptr"
# fix/null-ptr → "fix: null ptr"
BRANCH_DESC=$(echo "$HEAD" | sed 's|^feature/||;s|^fix/||')
if echo "$BRANCH_DESC" | grep -qE '^feat-'; then
TITLE="feat: $(echo "$BRANCH_DESC" | sed 's|^feat-||;s|-| |g')"
elif echo "$BRANCH_DESC" | grep -qE '^fix-'; then
TITLE="fix: $(echo "$BRANCH_DESC" | sed 's|^fix-||;s|-| |g')"
elif echo "$HEAD" | grep -qE '^fix/'; then
TITLE="fix: $(echo "$BRANCH_DESC" | sed 's|-| |g')"
else
TITLE="feat: $(echo "$BRANCH_DESC" | sed 's|-| |g')"
fi

echo "PR title: $TITLE"

# Check for existing open PR
PR_NUMBER=$(gh pr list \
--base dev \
--head "$HEAD" \
--state open \
--json number \
--jq '.[0].number')

if [ -n "$PR_NUMBER" ]; then
echo "PR #$PR_NUMBER already exists"
else
BODY="Automated PR: ${HEAD} -> dev. Auto-merge enabled - squash-merges when all required checks pass. Edit the PR title to a conventional commit format if needed."
gh pr create \
--base dev \
--head "$HEAD" \
--title "$TITLE" \
--body "$BODY"

PR_NUMBER=$(gh pr list \
--base dev \
--head "$HEAD" \
--state open \
--json number \
--jq '.[0].number')
echo "Created PR #$PR_NUMBER"
fi

gh pr merge "$PR_NUMBER" --auto --squash
echo "Auto-merge (squash) enabled on PR #$PR_NUMBER"
Loading
Loading