Skip to content

Commit a569915

Browse files
committed
Fix broken async db_transaction calls; add auto-tag/release workflow
The July 6 SQL-injection fix left ChirpHeliumKeysRpc.py and ChirpHeliumJoinRpc.py with a dead psycopg2-based db_transaction overload (shadowed by an async one) and psycopg2-style %(name)s query placeholders that asyncpg can't bind. Both get_merged_keys and add_session_key silently threw TypeError on every call, so device keys and join session records were never persisted. Switched to asyncpg's positional $1.. placeholders and made the call sites await db_transaction properly. Also dropped a stray "await db.close()" in db_fetch that referenced an undefined name. Added .github/workflows/release.yml to auto-tag and publish a GitHub Release (patch bump) on every push to master, which in turn triggers the existing container build workflow to publish a versioned image.
1 parent 9e23fe3 commit a569915

3 files changed

Lines changed: 85 additions & 39 deletions

File tree

.github/workflows/release.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: Tag and Release
2+
3+
# On every push to master, auto-bump the patch version (vX.Y.Z -> vX.Y.Z+1,
4+
# starting at v0.1.0 if no tags exist yet), tag it, and publish a GitHub
5+
# Release. Publishing the release triggers build-container-image.yml, which
6+
# builds and pushes the versioned container image to ghcr.io.
7+
8+
on:
9+
push:
10+
branches:
11+
- master
12+
13+
permissions:
14+
contents: write
15+
16+
concurrency:
17+
group: release
18+
cancel-in-progress: false
19+
20+
jobs:
21+
tag_and_release:
22+
runs-on: ubuntu-latest
23+
steps:
24+
- uses: actions/checkout@v4
25+
with:
26+
fetch-depth: 0
27+
28+
- name: Compute next version
29+
id: version
30+
run: |
31+
latest_tag=$(git tag -l 'v[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname | head -n1)
32+
if [ -z "$latest_tag" ]; then
33+
next_tag="v0.1.0"
34+
else
35+
IFS='.' read -r major minor patch <<< "${latest_tag#v}"
36+
next_tag="v${major}.${minor}.$((patch + 1))"
37+
fi
38+
echo "Latest tag: ${latest_tag:-<none>}, next tag: ${next_tag}"
39+
echo "tag=${next_tag}" >> "$GITHUB_OUTPUT"
40+
41+
- name: Create and push tag
42+
run: |
43+
git config user.name "github-actions[bot]"
44+
git config user.email "github-actions[bot]@users.noreply.github.com"
45+
git tag -a "${{ steps.version.outputs.tag }}" -m "Release ${{ steps.version.outputs.tag }}"
46+
git push origin "${{ steps.version.outputs.tag }}"
47+
48+
- name: Create GitHub release
49+
env:
50+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
51+
run: |
52+
gh release create "${{ steps.version.outputs.tag }}" \
53+
--title "${{ steps.version.outputs.tag }}" \
54+
--generate-notes

app/ChirpHeliumJoinRpc.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ def __init__(
3030
self.cs_grpc = chirpstack_host
3131
self.auth_token = [("authorization", f"Bearer {chirpstack_token}")]
3232

33-
async def db_transaction(self, query: str):
33+
async def db_transaction(self, query: str, *params):
3434
async with self.pool.acquire() as con:
3535
async with con.transaction():
36-
await con.execute(query)
36+
await con.execute(query, *params)
3737

3838
###########################################################################
3939
# follow internal redis stream gRPC for actionable changes
@@ -122,7 +122,7 @@ async def add_session_key(self, dev_eui):
122122
query = """
123123
INSERT INTO helium_devices
124124
(dev_eui, join_eui, dev_addr, max_copies, aps_key, nws_key, dev_name, fcnt_up, fcnt_down)
125-
VALUES (%(dev_eui)s, %(join_eui)s, %(dev_addr)s, %(max_copies)s, %(aps_key)s, %(nws_key)s, %(dev_name)s, %(fcnt_up)s, %(fcnt_down)s)
125+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
126126
ON CONFLICT (dev_eui) DO UPDATE
127127
SET join_eui = EXCLUDED.join_eui,
128128
dev_addr = EXCLUDED.dev_addr,
@@ -133,15 +133,15 @@ async def add_session_key(self, dev_eui):
133133
fcnt_up = EXCLUDED.fcnt_up,
134134
fcnt_down = EXCLUDED.fcnt_down;
135135
"""
136-
params = {
137-
"dev_eui": devices["devEui"],
138-
"join_eui": devices["joinEui"],
139-
"dev_addr": devices["devAddr"],
140-
"max_copies": max_copies,
141-
"aps_key": devices["appSKey"],
142-
"nws_key": devices["nwkSEncKey"],
143-
"dev_name": devices["name"],
144-
"fcnt_up": devices["fCntUp"],
145-
"fcnt_down": devices["nFCntDown"],
146-
}
147-
self.db_transaction(query, params)
136+
await self.db_transaction(
137+
query,
138+
devices["devEui"],
139+
devices["joinEui"],
140+
devices["devAddr"],
141+
max_copies,
142+
devices["appSKey"],
143+
devices["nwkSEncKey"],
144+
devices["name"],
145+
devices["fCntUp"],
146+
devices["nFCntDown"],
147+
)

app/ChirpHeliumKeysRpc.py

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,12 @@ def __init__(
2323
async def db_fetch(self, query: str):
2424
async with self.pool.acquire() as conn:
2525
async with conn.transaction():
26-
cur = await conn.fetch(query)
27-
await db.close()
28-
return cur
26+
return await conn.fetch(query)
2927

30-
def db_transaction(self, query: str, params=None):
31-
with psycopg2.connect(self.postgres) as con:
32-
with con.cursor() as cur:
33-
cur.execute(query, params)
34-
35-
async def db_transaction(self, query: str):
28+
async def db_transaction(self, query: str, *params):
3629
async with self.pool.acquire() as conn:
3730
async with conn.transaction():
38-
await conn.execute(query)
31+
await conn.execute(query, *params)
3932

4033
async def fetch_all_devices(self) -> list[str]:
4134
query = """
@@ -93,7 +86,7 @@ async def get_merged_keys(self, dev_eui: str) -> str:
9386
query = """
9487
INSERT INTO helium_devices
9588
(dev_eui, join_eui, dev_addr, max_copies, aps_key, nws_key, dev_name, fcnt_up, fcnt_down)
96-
VALUES (%(dev_eui)s, %(join_eui)s, %(dev_addr)s, %(max_copies)s, %(aps_key)s, %(nws_key)s, %(dev_name)s, %(fcnt_up)s, %(fcnt_down)s)
89+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
9790
ON CONFLICT (dev_eui) DO UPDATE
9891
SET join_eui = EXCLUDED.join_eui,
9992
dev_addr = EXCLUDED.dev_addr,
@@ -104,19 +97,18 @@ async def get_merged_keys(self, dev_eui: str) -> str:
10497
fcnt_up = EXCLUDED.fcnt_up,
10598
fcnt_down = EXCLUDED.fcnt_down;
10699
"""
107-
params = {
108-
"dev_eui": devices["devEui"],
109-
"join_eui": devices["joinEui"],
110-
"dev_addr": devices["devAddr"],
111-
"max_copies": max_copies,
112-
"aps_key": devices["appSKey"],
113-
"nws_key": devices["nwkSEncKey"],
114-
"dev_name": devices["name"],
115-
"fcnt_up": devices["fCntUp"],
116-
"fcnt_down": devices["nFCntDown"],
117-
}
118-
self.db_transaction(query, params)
119-
# await self.async_db_transaction(query)
100+
await self.db_transaction(
101+
query,
102+
devices["devEui"],
103+
devices["joinEui"],
104+
devices["devAddr"],
105+
max_copies,
106+
devices["appSKey"],
107+
devices["nwkSEncKey"],
108+
devices["name"],
109+
devices["fCntUp"],
110+
devices["nFCntDown"],
111+
)
120112
return f"Updated: {dev_eui}"
121113

122114
async def helium_skfs_update(self):

0 commit comments

Comments
 (0)