Skip to content

Commit 9776ce2

Browse files
committed
[IMP] move warehouse fetching to odoo dialect / version adapter, add release github workflow
1 parent 17225ff commit 9776ce2

5 files changed

Lines changed: 141 additions & 30 deletions

File tree

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
name: release-binaries
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
workflow_dispatch:
8+
inputs:
9+
tag:
10+
description: "Existing git tag to release (for example: v0.1.0)"
11+
required: true
12+
type: string
13+
14+
permissions:
15+
contents: write
16+
17+
env:
18+
BINARY_NAME: odoo-rapid-quant
19+
TARGET: x86_64-unknown-linux-musl
20+
21+
jobs:
22+
build-and-publish:
23+
name: build-and-publish-linux-musl
24+
runs-on: ubuntu-24.04
25+
26+
steps:
27+
- name: Checkout
28+
uses: actions/checkout@v6
29+
with:
30+
fetch-depth: 0
31+
32+
- name: Resolve release tag
33+
shell: bash
34+
run: |
35+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
36+
echo "RELEASE_TAG=${{ github.event.inputs.tag }}" >> "$GITHUB_ENV"
37+
else
38+
echo "RELEASE_TAG=${GITHUB_REF_NAME}" >> "$GITHUB_ENV"
39+
fi
40+
41+
- name: Checkout requested tag
42+
if: github.event_name == 'workflow_dispatch'
43+
shell: bash
44+
run: git checkout "${RELEASE_TAG}"
45+
46+
- name: Validate tag matches Cargo.toml version
47+
shell: bash
48+
run: |
49+
tag_version="${RELEASE_TAG#v}"
50+
manifest_version="$(python -c 'import tomllib; print(tomllib.load(open("Cargo.toml", "rb"))["package"]["version"])')"
51+
52+
if [ "${tag_version}" != "${manifest_version}" ]; then
53+
echo "::error::Tag ${RELEASE_TAG} does not match Cargo.toml version ${manifest_version}"
54+
exit 1
55+
fi
56+
57+
- name: Install Rust toolchain
58+
uses: dtolnay/rust-toolchain@stable
59+
with:
60+
targets: ${{ env.TARGET }}
61+
62+
- name: Cache Rust dependencies
63+
uses: Swatinem/rust-cache@v2
64+
with:
65+
key: ${{ env.TARGET }}
66+
67+
- name: Install musl toolchain
68+
shell: bash
69+
run: |
70+
sudo apt-get update
71+
sudo apt-get install -y musl-tools
72+
73+
- name: Build static Linux binary
74+
shell: bash
75+
run: cargo build --locked --release --target "${TARGET}"
76+
77+
- name: Verify static linking
78+
shell: bash
79+
run: |
80+
binary_path="target/${TARGET}/release/${BINARY_NAME}"
81+
ldd_output="$(ldd "${binary_path}" 2>&1 || true)"
82+
echo "${ldd_output}"
83+
if ! grep -Eq "not a dynamic executable|statically linked" <<< "${ldd_output}"; then
84+
echo "Expected a static musl binary, but binary appears dynamically linked."
85+
exit 1
86+
fi
87+
88+
- name: Package release archive
89+
shell: bash
90+
run: |
91+
mkdir -p dist
92+
cp "target/${TARGET}/release/${BINARY_NAME}" "dist/${BINARY_NAME}"
93+
cp LICENSE "dist/LICENSE"
94+
archive="${BINARY_NAME}-${RELEASE_TAG}-${TARGET}.tar.gz"
95+
tar -C dist -czf "dist/${archive}" "${BINARY_NAME}" "LICENSE"
96+
rm "dist/${BINARY_NAME}" "dist/LICENSE"
97+
98+
- name: Generate checksums
99+
shell: bash
100+
run: |
101+
cd dist
102+
sha256sum * > SHA256SUMS
103+
104+
- name: Create or update GitHub release
105+
uses: softprops/action-gh-release@v2
106+
with:
107+
tag_name: ${{ env.RELEASE_TAG }}
108+
files: |
109+
dist/*
110+
generate_release_notes: true
111+
env:
112+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

src/dialect/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use sqlx::PgPool;
88
use crate::{
99
odoo::OdooVersion,
1010
product::{Product, ProductId, Quant},
11+
warehouse::Warehouse,
1112
};
1213

1314
pub mod v15;
@@ -37,6 +38,8 @@ pub trait OdooAdapter: Send + Sync {
3738
decimal_precision: u32,
3839
raw_quants: &mut HashMap<ProductId, Quant>,
3940
) -> Result<(), sqlx::Error>;
41+
42+
async fn warehouse(&self, pool: &PgPool, id: i32) -> Result<Warehouse, sqlx::Error>;
4043
}
4144

4245
#[derive(Debug)]

src/dialect/v15.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::{
1010
dialect::OdooAdapter,
1111
odoo::OdooVersion,
1212
product::{Product, ProductId, Quant},
13+
warehouse::Warehouse,
1314
};
1415

1516
pub struct Adapter {
@@ -377,4 +378,28 @@ impl OdooAdapter for Adapter {
377378

378379
Ok(())
379380
}
381+
382+
async fn warehouse(&self, pool: &PgPool, id: i32) -> Result<Warehouse, sqlx::Error> {
383+
sqlx::query_as::<_, Warehouse>(
384+
"
385+
SELECT
386+
stock_warehouse.id,
387+
stock_location.parent_path || '%' as location_path,
388+
stock_warehouse.name
389+
FROM stock_warehouse
390+
INNER JOIN stock_location ON stock_location.id = stock_warehouse.lot_stock_id
391+
WHERE
392+
stock_warehouse.id = $1
393+
AND
394+
stock_warehouse.active is true
395+
AND
396+
stock_location.active is true
397+
AND
398+
stock_location.usage = 'internal'
399+
",
400+
)
401+
.bind(id)
402+
.fetch_one(pool)
403+
.await
404+
}
380405
}

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ async fn main() -> anyhow::Result<()> {
9292
let adapter = detected.dialect(&src_pool).await?;
9393
tracing::info!("Using adapter for Odoo major {}.", adapter.major());
9494

95-
let warehouse = warehouse::one(&src_pool, cli.warehouse).await?;
95+
let warehouse = adapter.warehouse(&src_pool, cli.warehouse).await?;
9696

9797
let mut graph = product::Graph::new(src_pool, warehouse.clone(), adapter).await?;
9898

src/warehouse.rs

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
use std::ops::Deref;
22

3-
use sqlx::PgPool;
4-
53
#[derive(sqlx::Type, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, Clone, Copy)]
64
#[sqlx(transparent)]
75
pub struct WarehouseId(pub i32);
@@ -15,35 +13,8 @@ impl Deref for WarehouseId {
1513
}
1614

1715
#[derive(sqlx::FromRow, Debug, Clone)]
18-
#[allow(unused)]
1916
pub struct Warehouse {
2017
pub id: WarehouseId,
2118
pub location_path: String,
2219
pub name: String,
23-
pub sequence: i32,
24-
}
25-
26-
pub async fn one(pool: &PgPool, id: i32) -> Result<Warehouse, sqlx::Error> {
27-
sqlx::query_as::<_, Warehouse>(
28-
"
29-
SELECT
30-
stock_warehouse.id,
31-
stock_location.parent_path || '%' as location_path,
32-
stock_warehouse.name,
33-
stock_warehouse.sequence
34-
FROM stock_warehouse
35-
INNER JOIN stock_location ON stock_location.id = stock_warehouse.lot_stock_id
36-
WHERE
37-
stock_warehouse.id = $1
38-
AND
39-
stock_warehouse.active is true
40-
AND
41-
stock_location.active is true
42-
AND
43-
stock_location.usage = 'internal'
44-
",
45-
)
46-
.bind(id)
47-
.fetch_one(pool)
48-
.await
4920
}

0 commit comments

Comments
 (0)