Skip to content

Commit 1620a4b

Browse files
tbitcsoz-agent
andcommitted
fix: restore CI/CD workflows overwritten by upgrade --full
- Restore ci.yml (develop branch trigger was removed by template) - Restore dev-release.yml (template had broken sed + wrong artifact versions) - Fix upgrader: --full no longer overwrites existing CI configs (only creates CI files if none exist — prevents template from clobbering customized workflows) Co-Authored-By: Oz <oz-agent@warp.dev>
1 parent aa2d82d commit 1620a4b

3 files changed

Lines changed: 122 additions & 44 deletions

File tree

.github/workflows/ci.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ name: CI
22

33
on:
44
push:
5-
branches: [main]
5+
branches: [main, develop]
66
pull_request:
7-
branches: [main]
7+
branches: [main, develop]
88

99
concurrency:
1010
group: ci-${{ github.ref }}
@@ -22,9 +22,9 @@ jobs:
2222
with:
2323
python-version: "3.12"
2424
cache: pip
25-
- run: pip install -e ".[dev]"
26-
- run: ruff check
27-
- run: ruff format --check .
25+
- run: pip install ruff
26+
- run: ruff check src/ tests/
27+
- run: ruff format --check src/ tests/
2828

2929
typecheck:
3030
runs-on: ubuntu-latest
@@ -62,6 +62,6 @@ jobs:
6262
with:
6363
python-version: "3.12"
6464
cache: pip
65-
- run: pip install -e .
6665
- run: pip install pip-audit
66+
- run: pip install -e .
6767
- run: pip-audit

.github/workflows/dev-release.yml

Lines changed: 96 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,29 @@ permissions:
99
contents: read
1010

1111
jobs:
12-
dev-build:
12+
test:
1313
runs-on: ubuntu-latest
14+
# Only run from the develop branch — blocks accidental workflow_dispatch from main.
15+
if: github.ref == 'refs/heads/develop'
16+
steps:
17+
- uses: actions/checkout@v6
18+
- uses: actions/setup-python@v6
19+
with:
20+
python-version: "3.12"
21+
cache: pip
22+
- run: pip install -e ".[dev]"
23+
- run: ruff check src/ tests/
24+
- run: ruff format --check src/ tests/
25+
- run: mypy src/specsmith --ignore-missing-imports
26+
- run: pytest tests/ -x -q
27+
28+
build-and-publish:
29+
needs: test
30+
runs-on: ubuntu-latest
31+
environment: pypi
32+
permissions:
33+
contents: read
34+
id-token: write
1435
steps:
1536
- uses: actions/checkout@v6
1637
with:
@@ -26,37 +47,84 @@ jobs:
2647

2748
- name: Set dev version
2849
run: |
29-
BASE=$(grep 'version = ' pyproject.toml | head -1 | sed 's/version = "\(.*\)"//')
30-
MAJOR=$(echo $BASE | cut -d. -f1)
31-
MINOR=$(echo $BASE | cut -d. -f2)
32-
PATCH=$(echo $BASE | cut -d. -f3)
33-
NP=$((PATCH + 1))
34-
TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo HEAD~100)
35-
NC=$(git rev-list --count HEAD ^$TAG 2>/dev/null || echo 0)
36-
DV="${MAJOR}.${MINOR}.${NP}.dev${NC}"
37-
echo "DEV_VERSION=${DV}" >> $GITHUB_ENV
38-
sed -i "s/version = "${BASE}"/version = "${DV}"/" pyproject.toml
39-
echo "Building version: ${DV}"
50+
# Use pyproject.toml version as the base (no patch bump).
51+
# pyproject.toml should always hold the NEXT release version (e.g. 0.3.0).
52+
# Dev builds publish as 0.3.0.devN — PEP 440 pre-release of the upcoming release.
53+
# N = total commit count (monotonically increasing, unique per push).
54+
BASE_VERSION=$(grep 'version = ' pyproject.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
55+
COMMIT_COUNT=$(git rev-list --count HEAD)
56+
DEV_VERSION="${BASE_VERSION}.dev${COMMIT_COUNT}"
57+
echo "DEV_VERSION=${DEV_VERSION}" >> $GITHUB_ENV
58+
59+
# Patch pyproject.toml with dev version
60+
sed -i "s/version = \"${BASE_VERSION}\"/version = \"${DEV_VERSION}\"/" pyproject.toml
61+
echo "Building version: ${DEV_VERSION}"
4062
4163
- run: python -m build
4264

43-
- name: Upload build artifacts
44-
uses: actions/upload-artifact@v7
45-
with:
46-
name: dev-dist
47-
path: dist/
65+
- name: Publish dev release to PyPI
66+
uses: pypa/gh-action-pypi-publish@release/v1
67+
continue-on-error: true # version already exists on PyPI is not a failure
4868

49-
pypi-dev-publish:
50-
needs: dev-build
69+
docs-build:
70+
needs: build-and-publish
5171
runs-on: ubuntu-latest
52-
environment: pypi
53-
permissions:
54-
id-token: write
5572
continue-on-error: true
5673
steps:
57-
- uses: actions/download-artifact@v8
58-
with:
59-
name: dev-dist
60-
path: dist/
61-
- name: Publish dev release to PyPI
62-
uses: pypa/gh-action-pypi-publish@release/v1
74+
- name: Trigger ReadTheDocs builds (develop + latest)
75+
env:
76+
RTD_TOKEN: ${{ secrets.RTD_TOKEN }}
77+
run: |
78+
if [ -z "$RTD_TOKEN" ]; then
79+
echo "WARNING: RTD_TOKEN secret is not set. Skipping RTD build trigger."
80+
echo "To fix: go to GitHub repo Settings → Secrets → Actions and add RTD_TOKEN."
81+
echo "Get the token from: https://readthedocs.org/accounts/tokens/"
82+
exit 0
83+
fi
84+
85+
# Trigger the 'develop' RTD version build (accessible at /en/develop/)
86+
echo "Triggering RTD build for 'develop' version..."
87+
STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
88+
-H "Authorization: Token $RTD_TOKEN" \
89+
"https://readthedocs.org/api/v3/projects/specsmith/versions/develop/builds/")
90+
echo "RTD develop build trigger: HTTP $STATUS"
91+
if [ "$STATUS" != "202" ]; then
92+
echo "WARNING: RTD develop build trigger returned HTTP $STATUS (expected 202)."
93+
echo "Common causes:"
94+
echo " - 401: RTD_TOKEN is invalid or expired"
95+
echo " - 404: 'develop' version not activated in RTD dashboard"
96+
echo " Fix: https://readthedocs.org/projects/specsmith/versions/ → activate 'develop'"
97+
fi
98+
99+
# Step 1: Set RTD project default_branch to 'develop'
100+
echo "[1/3] Setting RTD project default_branch to 'develop'..."
101+
PATCH_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X PATCH \
102+
-H "Authorization: Token $RTD_TOKEN" \
103+
-H "Content-Type: application/json" \
104+
-d '{"default_branch": "develop"}' \
105+
"https://readthedocs.org/api/v3/projects/specsmith/")
106+
echo "RTD project PATCH: HTTP $PATCH_STATUS"
107+
108+
# Step 2: Set the 'latest' VERSION object's identifier to 'develop'
109+
# This is the key step — the version object has its own branch setting
110+
# separate from the project-level default_branch.
111+
echo "[2/3] Setting RTD 'latest' version identifier to 'develop'..."
112+
VER_PATCH=$(curl -s -o /tmp/ver_patch.txt -w "%{http_code}" -X PATCH \
113+
-H "Authorization: Token $RTD_TOKEN" \
114+
-H "Content-Type: application/json" \
115+
-d '{"identifier": "develop", "active": true}' \
116+
"https://readthedocs.org/api/v3/projects/specsmith/versions/latest/")
117+
echo "RTD 'latest' version PATCH: HTTP $VER_PATCH"
118+
cat /tmp/ver_patch.txt | head -c 200 || true
119+
120+
# Step 3: Trigger a fresh /en/latest/ build (now tracks develop)
121+
echo "[3/3] Triggering RTD 'latest' build from develop..."
122+
LATEST_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
123+
-H "Authorization: Token $RTD_TOKEN" \
124+
"https://readthedocs.org/api/v3/projects/specsmith/versions/latest/builds/")
125+
echo "RTD latest build trigger: HTTP $LATEST_STATUS"
126+
if [ "$LATEST_STATUS" != "202" ]; then
127+
echo "WARNING: RTD latest trigger returned HTTP $LATEST_STATUS"
128+
echo "If 404: 'latest' version may not be active in RTD dashboard."
129+
echo "Fix: https://readthedocs.org/projects/specsmith/versions/ -> activate 'latest'"
130+
fi

src/specsmith/upgrader.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -235,17 +235,27 @@ def _sync_full(
235235
except ValueError:
236236
pass
237237

238-
# 3. VCS CI configs — regenerate
238+
# 3. VCS CI configs — create only if missing (never overwrite user CI)
239239
if config.vcs_platform:
240-
try:
241-
from specsmith.vcs import get_platform
242-
243-
platform = get_platform(config.vcs_platform)
244-
files = platform.generate_all(config, root)
245-
for f in files:
246-
synced.append(str(f.relative_to(root)))
247-
except ValueError:
248-
pass
240+
ci_exists = (
241+
(
242+
list((root / ".github" / "workflows").glob("*.yml"))
243+
if (root / ".github" / "workflows").is_dir()
244+
else []
245+
)
246+
or (root / ".gitlab-ci.yml").exists()
247+
or (root / "bitbucket-pipelines.yml").exists()
248+
)
249+
if not ci_exists:
250+
try:
251+
from specsmith.vcs import get_platform
252+
253+
platform = get_platform(config.vcs_platform)
254+
files = platform.generate_all(config, root)
255+
for f in files:
256+
synced.append(str(f.relative_to(root)) + " (created)")
257+
except ValueError:
258+
pass
249259

250260
# 4. Community files — create only if missing
251261
for tmpl_name, output_rel in _build_community_files(config):

0 commit comments

Comments
 (0)