README
¶
Hi, this is Deploya!
What it does?
- It generates a
ci.ymlfile that will get triggered on push or PR on main branch - It will generate basic jobs like test, build, notification to your corporate messaging app (e.g. Slack, Discord, or your boss's email if required)
- Generates a build summary of CI runs
- Generates Release pipeline for your product semantic github release
- Creates beautiful GitHub Pull Requests (
deploya pr) containing all unmerged commits from your branch, with AI summaries powered by Google Gemini (free API key available)
Why?
Because we hate creating ci.yml and sometimes a basic one will also work. Yet it can be upgraded to handle some repetitive tasks.
How to run
go build .
# it will create deploya binary and you can run it with
deploya init
# or
go run main.go init
What can it do?
It can detect some popular languages like Python, Go, JS/TS (Node), Java, Rust, Ruby based upon the directory and the files they have.
Example: it detects Python by looking into pyproject.toml or requirements.txt like files, and Go from go.mod file.
How it works
- Detects programming language
- Asks user if they need webhook integration or not for messaging
- Asks user if they are using any container registry — only available if the project has a visible
Dockerfile - Creates
ci.yml
What can be added?
A lot of things.. will update about it later.
Example


generated CI file for a python project
name: CI — your-repo-name
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
env:
IMAGE_NAME: your-image-name
jobs:
# ── Build & Test ────────────────────────────────────────────
test:
name: Build & Test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
# - name: Run tests
# run: pytest
# ── Docker Build & Push ─────────────────────────────────────
docker:
name: Build & Push Docker image
runs-on: ubuntu-latest
needs: test
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push to GHCR
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.ref == 'refs/heads/main' }}
tags: ghcr.io/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
# ── Notify ──────────────────────────────────────────────────
notify:
name: Discord Notification
runs-on: ubuntu-latest
needs: [test, docker]
if: always()
steps:
- name: Notify Discord
uses: tsickert/discord-webhook@v6.0.0
with:
webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}
embed-title: "${{ needs.test.result == 'success' && '✅ Pipeline Passed' || '❌ Pipeline Failed' }} — Tour-Stories"
embed-color: "${{ needs.test.result == 'success' && '3066993' || '15158332' }}"
embed-description: |
**Repository** : Tour-Stories
**Branch** : ${{ github.ref_name }}
**Language** : python 3.11
**Triggered by**: ${{ github.actor }}
**Commit** : ${{ github.sha }}
**Tests** : ${{ needs.test.result }}
**Docker** : ${{ needs.docker.result }}
[🔗 View Run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
# ── Summary ─────────────────────────────────────────────────
summary:
name: Summary
runs-on: ubuntu-latest
needs: [test, docker]
if: always()
steps:
- name: Pipeline summary
run: |
echo "## 📊 CI Summary — Tour-Stories" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| | Details |" >> $GITHUB_STEP_SUMMARY
echo "|---|---|" >> $GITHUB_STEP_SUMMARY
echo "| 🔤 Language | python 3.11 |" >> $GITHUB_STEP_SUMMARY
echo "| 🌿 Branch | ${{ github.ref_name }} |" >> $GITHUB_STEP_SUMMARY
echo "| 📝 Commit | ${{ github.sha }} |" >> $GITHUB_STEP_SUMMARY
echo "| 👤 Triggered by | ${{ github.actor }} |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Jobs" >> $GITHUB_STEP_SUMMARY
echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY
echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY
echo "| 🧪 Tests | ${{ needs.test.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| 🐳 Docker | ${{ needs.docker.result }} |" >> $GITHUB_STEP_SUMMARY
Create Beautiful Pull Requests with AI (deploya pr)
Create stunning GitHub Pull Requests directly from your terminal!
# Run on any feature branch:
deploya pr
# Common options:
deploya pr --base main --draft # Open a draft PR against main
deploya pr --dry-run # Preview title & body without opening PR
deploya pr -y # Non-interactive / skip confirmation prompt
deploya pr --web # Open PR in your browser after creation
✨ Features:
- Automatic Unmerged Commits Range: Identifies all commits from your current branch that haven't been merged into the base branch (
origin/<base>..HEAD). - AI-Powered with Google Gemini: Automatically generates professional, comprehensive PR titles and descriptions with an Overview, Key Changes, Architectural Notes, and Review Checklists.
- Free Gemini API Support: Google Gemini API keys are 100% free with generous tier limits from Google AI Studio. Export it in your shell:
export GEMINI_API_KEY=your_free_gemini_api_key - Built-in Fallback Generator: If no AI key is provided, Deploya formats a beautiful conventional-commits categorized description with git diff stats and review checklists.
- Auto Push Check: Checks if your local branch is ahead of remote
originand automatically pushes it before submitting the PR to GitHub. - GitHub Auth: Reads
GH_TOKEN,GITHUB_TOKEN, or seamlessly authenticates via the GitHub CLI (gh auth login).
If you want to generate release without any pain
Create a .releaserc file in your working directory with following Basic config and let deploya init do the job for you !!
on_branch: main # on which branch you want release to take place
from_branch: dev # this might not be needed as the product is under development
current_version: 0.1.1 # your current release version or github tag, if it is initial keep it `0.0.0`
tag_prefix: v # tag prefix eg: v0.0.1, or whatever prefix you want
archive: true # build cross-platform binary archives (Go projects) and attach them to the release
registry: ghcr # push a container image tagged with the release version (needs a Dockerfile; ghcr only for now)
github_repo: kushalsubedi/deploya # your github repo
categories:
# release types and commit typos
features: [feat, feature]
fixes: [fix, bugfix, bug]
patches: [chore, refactor, perf, improvement]
docs: [docs, doc]
Monorepo & modular releases
Deploya releases packages, not just repos. Add a packages: list to
.releaserc and every package gets its own version line, bumped only from the
commits that touched its path.
deploya init detects this for you — it reads go.work, pnpm-workspace.yaml,
the package.json workspaces field, lerna.json or a Cargo workspace,
proposes the package list, and works out the dependency links between them.
github_repo: acme/platform
mode: independent # or: locked
packages:
- name: api
path: services/api
current_version: v1.2.0
archive: true # cross-platform binaries, Go packages only
- name: web
path: apps/web
current_version: v0.4.0
depends_on: [api] # releasing api re-releases web
groups: # named product units
platform: [api, worker, gateway]
frontend: [web, admin]
deploya release # every package with changes
deploya release --only api,worker # just these
deploya release --group platform # a configured group
deploya release --dry-run # plan only, no token needed
Will release (independent mode):
• api api/v1.2.0 → api/v2.0.0 (major, 3 commits, commits)
• web web/v0.4.0 → web/v0.4.1 (patch, 0 commits, dependency bump (api))
Skipped:
· docs no commits since docs/v1.0.0
What you get per package:
| Tags | api/v2.0.0 — one tag line per package, never mixed |
| Releases | one GitHub release each, with its own notes |
| Changelogs | services/api/CHANGELOG.md, next to the code it describes |
| Binaries | api_v2.0.0_linux_amd64.tar.gz built from the package directory |
| Images | ghcr.io/acme/platform/api:v2.0.0 — one image per package |
Modes. independent (default) gives every package its own version.
locked keeps one version across the repo: a single tag, a single release, and
notes listing which packages actually moved.
Dependency cascade. depends_on means a package is re-released whenever one
of its dependencies is, with a patch bump and a note saying why. It propagates
transitively, so A → B → C all move together.
Org-level releases
One manifest, many repos. deploya org init scaffolds deploya.org.yml:
org: acme
workspace: .deploya/repos # where repos without a local checkout are cloned
repos:
- repo: acme/platform
dir: ../platform # existing checkout; omit to let deploya clone it
group: platform # which packages inside that repo to release
- repo: acme/docs
deploya org status # what is unreleased across the whole portfolio
deploya org release # cut them all — a failing repo never stops the others
✅ acme/platform api/v2.0.0, web/v0.4.1
⬆️ acme/docs 1 unit(s) pending release
❌ acme/legacy could not load .releaserc
Each repo keeps its own .releaserc; the manifest only says which repos belong
to the product. Needs GH_TOKEN (or GITHUB_TOKEN) with access to each repo.
Documentation
¶
There is no documentation for this package.