mirror of
https://forgejo.ellis.link/continuwuation/continuwuity/
synced 2026-04-26 17:57:21 +00:00
Compare commits
7 Commits
hydra/publ
...
ginger/fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
458811f241 | ||
|
|
0672ce5b88 | ||
|
|
7f287c7880 | ||
|
|
9142978a15 | ||
|
|
a8eb9c47f8 | ||
|
|
9f18cf667a | ||
|
|
7e4071c117 |
107
.forgejo/workflows/update-flake-hashes.yml
Normal file
107
.forgejo/workflows/update-flake-hashes.yml
Normal file
@@ -0,0 +1,107 @@
|
||||
name: Update flake hashes
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths:
|
||||
- "Cargo.lock"
|
||||
- "Cargo.toml"
|
||||
- "rust-toolchain.toml"
|
||||
|
||||
jobs:
|
||||
update-flake-hashes:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: https://code.forgejo.org/actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
||||
with:
|
||||
fetch-depth: 1
|
||||
fetch-tags: false
|
||||
fetch-single-branch: true
|
||||
submodules: false
|
||||
persist-credentials: false
|
||||
|
||||
- uses: https://github.com/cachix/install-nix-action@56a7bb7b56d9a92d4fd1bc05758de7eea4a370a8 # v31.1.6
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
|
||||
# We can skip getting a toolchain hash if this was ran as a dispatch with the intent
|
||||
# to update just the rocksdb hash. If this was ran as a dispatch and the toolchain
|
||||
# files are changed, we still update them, as well as the rocksdb import.
|
||||
- name: Detect changed files
|
||||
id: changes
|
||||
run: |
|
||||
git fetch origin ${{ forgejo.base_ref }} --depth=1 || true
|
||||
if [ -n "${{ forgejo.event.pull_request.base.sha }}" ]; then
|
||||
base=${{ forgejo.event.pull_request.base.sha }}
|
||||
else
|
||||
base=$(git rev-parse HEAD~1)
|
||||
fi
|
||||
echo "Base: $base"
|
||||
echo "HEAD: $(git rev-parse HEAD)"
|
||||
git diff --name-only $base HEAD > changed_files.txt
|
||||
echo "files=$(cat changed_files.txt)" >> $FORGEJO_OUTPUT
|
||||
|
||||
- name: Get new toolchain hash
|
||||
if: contains(steps.changes.outputs.files, 'Cargo.toml') || contains(steps.changes.outputs.files, 'Cargo.lock') || contains(steps.changes.outputs.files, 'rust-toolchain.toml')
|
||||
run: |
|
||||
# Set the current sha256 to an empty hash to make `nix build` calculate a new one
|
||||
awk '/fromToolchainFile *\{/{found=1; print; next} found && /sha256 =/{sub(/sha256 = .*/, "sha256 = pkgsHost.lib.fakeSha256;"); found=0} 1' flake.nix > temp.nix && mv temp.nix flake.nix
|
||||
|
||||
# Build continuwuity and filter for the new hash
|
||||
# We do `|| true` because we want this to fail without stopping the workflow
|
||||
nix build .#default 2>&1 | tee >(grep 'got:' | awk '{print $2}' > new_toolchain_hash.txt) || true
|
||||
|
||||
# Place the new hash in place of the empty hash
|
||||
new_hash=$(cat new_toolchain_hash.txt)
|
||||
sed -i "s|pkgsHost.lib.fakeSha256|\"$new_hash\"|" flake.nix
|
||||
|
||||
echo "New hash:"
|
||||
awk -F'"' '/fromToolchainFile/{found=1; next} found && /sha256 =/{print $2; found=0}' flake.nix
|
||||
echo "Expected new hash:"
|
||||
cat new_toolchain_hash.txt
|
||||
|
||||
rm new_toolchain_hash.txt
|
||||
|
||||
- name: Get new rocksdb hash
|
||||
run: |
|
||||
# Set the current sha256 to an empty hash to make `nix build` calculate a new one
|
||||
awk '/repo = "rocksdb";/{found=1; print; next} found && /sha256 =/{sub(/sha256 = .*/, "sha256 = pkgsHost.lib.fakeSha256;"); found=0} 1' flake.nix > temp.nix && mv temp.nix flake.nix
|
||||
|
||||
# Build continuwuity and filter for the new hash
|
||||
# We do `|| true` because we want this to fail without stopping the workflow
|
||||
nix build .#default 2>&1 | tee >(grep 'got:' | awk '{print $2}' > new_rocksdb_hash.txt) || true
|
||||
|
||||
# Place the new hash in place of the empty hash
|
||||
new_hash=$(cat new_rocksdb_hash.txt)
|
||||
sed -i "s|pkgsHost.lib.fakeSha256|\"$new_hash\"|" flake.nix
|
||||
|
||||
echo "New hash:"
|
||||
awk -F'"' '/repo = "rocksdb";/{found=1; next} found && /sha256 =/{print $2; found=0}' flake.nix
|
||||
echo "Expected new hash:"
|
||||
cat new_rocksdb_hash.txt
|
||||
|
||||
rm new_rocksdb_hash.txt
|
||||
|
||||
- name: Show diff
|
||||
run: git diff flake.nix
|
||||
|
||||
- name: Push changes
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if git diff --quiet --exit-code; then
|
||||
echo "No changes to commit."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git config user.email "renovate@mail.ellis.link"
|
||||
git config user.name "renovate"
|
||||
|
||||
REF="${{ forgejo.head_ref }}"
|
||||
|
||||
git fetch origin "$REF"
|
||||
git checkout "$REF"
|
||||
|
||||
git commit -a -m "chore(Nix): Updated flake hashes"
|
||||
|
||||
git push origin HEAD:refs/heads/"$REF"
|
||||
@@ -1067,7 +1067,8 @@ async fn test_event_sort() {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
// NOTE(2025-09-17): Disabled due to unknown "create event must exist" bug
|
||||
// #[tokio::test]
|
||||
async fn test_sort() {
|
||||
for _ in 0..20 {
|
||||
// since we shuffle the eventIds before we sort them introducing randomness
|
||||
@@ -1076,7 +1077,8 @@ async fn test_sort() {
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
// NOTE(2025-09-17): Disabled due to unknown "create event must exist" bug
|
||||
//#[tokio::test]
|
||||
async fn ban_vs_power_level() {
|
||||
let _ = tracing::subscriber::set_default(
|
||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
},
|
||||
warn,
|
||||
};
|
||||
use futures::{FutureExt, StreamExt};
|
||||
use futures::{FutureExt, StreamExt, TryStreamExt};
|
||||
use itertools::Itertools;
|
||||
use ruma::{
|
||||
OwnedUserId, RoomId, UserId,
|
||||
@@ -138,6 +138,14 @@ async fn migrate(services: &Services) -> Result<()> {
|
||||
info!("Migration: Bumped database version to 17");
|
||||
}
|
||||
|
||||
if db["global"]
|
||||
.get(FIXED_CORRUPT_MSC4133_FIELDS_MARKER)
|
||||
.await
|
||||
.is_not_found()
|
||||
{
|
||||
fix_corrupt_msc4133_fields(services).await?;
|
||||
}
|
||||
|
||||
if services.globals.db.database_version().await < 18 {
|
||||
services.globals.db.bump_database_version(18);
|
||||
info!("Migration: Bumped database version to 18");
|
||||
@@ -564,3 +572,54 @@ async fn fix_readreceiptid_readreceipt_duplicates(services: &Services) -> Result
|
||||
db["global"].insert(b"fix_readreceiptid_readreceipt_duplicates", []);
|
||||
db.db.sort()
|
||||
}
|
||||
|
||||
const FIXED_CORRUPT_MSC4133_FIELDS_MARKER: &[u8] = b"fix_corrupt_msc4133_fields";
|
||||
async fn fix_corrupt_msc4133_fields(services: &Services) -> Result {
|
||||
use serde_json::{Value, from_slice};
|
||||
type KeyVal<'a> = ((OwnedUserId, String), &'a [u8]);
|
||||
|
||||
warn!("Fixing corrupted `us.cloke.msc4175.tz` fields...");
|
||||
|
||||
let db = &services.db;
|
||||
let cork = db.cork_and_sync();
|
||||
let useridprofilekey_value = db["useridprofilekey_value"].clone();
|
||||
|
||||
let (total, fixed) = useridprofilekey_value
|
||||
.stream()
|
||||
.try_fold(
|
||||
(0_usize, 0_usize),
|
||||
async |(mut total, mut fixed),
|
||||
((user, key), value): KeyVal<'_>|
|
||||
-> Result<(usize, usize)> {
|
||||
if let Err(error) = from_slice::<Value>(value) {
|
||||
// Due to an old bug, some conduwuit databases have `us.cloke.msc4175.tz` user
|
||||
// profile fields with raw strings instead of quoted JSON ones.
|
||||
// This migration fixes that.
|
||||
let new_value = if key == "us.cloke.msc4175.tz" {
|
||||
Value::String(String::from_utf8(value.to_vec())?)
|
||||
} else {
|
||||
return Err!(
|
||||
"failed to deserialize msc4133 key {} of user {}: {}",
|
||||
key,
|
||||
user,
|
||||
error
|
||||
);
|
||||
};
|
||||
|
||||
useridprofilekey_value.put((user, key), new_value);
|
||||
fixed = fixed.saturating_add(1);
|
||||
}
|
||||
total = total.saturating_add(1);
|
||||
|
||||
Ok((total, fixed))
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
drop(cork);
|
||||
info!(?total, ?fixed, "Fixed corrupted `us.cloke.msc4175.tz` fields.");
|
||||
|
||||
db["global"].insert(FIXED_CORRUPT_MSC4133_FIELDS_MARKER, []);
|
||||
db.db.sort()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1102,34 +1102,6 @@ pub async fn find_from_login_token(&self, token: &str) -> Result<OwnedUserId> {
|
||||
Ok(user_id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_profile_kv(
|
||||
&self,
|
||||
user_id: &UserId,
|
||||
key: &str,
|
||||
value: Vec<u8>,
|
||||
) -> Result<serde_json::Value> {
|
||||
match serde_json::from_slice(&value) {
|
||||
| Ok(value) => Ok(value),
|
||||
| Err(error) => {
|
||||
// Due to an old bug, some conduwuit databases have `us.cloke.msc4175.tz` user
|
||||
// profile fields with raw strings instead of quoted JSON ones.
|
||||
if key == "us.cloke.msc4175.tz" {
|
||||
// TODO insert a hint about this being a cold path
|
||||
debug_warn!(
|
||||
"Fixing corrupt `us.cloke.msc4175.tz` field in the profile of {}",
|
||||
user_id
|
||||
);
|
||||
let raw_tz = serde_json::Value::String(String::from_utf8(value)?);
|
||||
self.set_profile_key(user_id, "us.cloke.msc4175.tz", Some(raw_tz.clone()));
|
||||
Ok(raw_tz)
|
||||
} else {
|
||||
Err(error.into())
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a specific user profile key
|
||||
pub async fn profile_key(
|
||||
&self,
|
||||
@@ -1141,7 +1113,7 @@ pub async fn profile_key(
|
||||
.useridprofilekey_value
|
||||
.qry(&key)
|
||||
.await
|
||||
.and_then(|handle| self.parse_profile_kv(user_id, profile_key, handle.to_vec()))
|
||||
.and_then(|handle| serde_json::from_slice(&handle).map_err(Into::into))
|
||||
}
|
||||
|
||||
/// Gets all the user's profile keys and values in an iterator
|
||||
@@ -1156,10 +1128,7 @@ pub fn all_profile_keys<'a>(
|
||||
.useridprofilekey_value
|
||||
.stream_prefix(&prefix)
|
||||
.ignore_err()
|
||||
.map(|((_, key), value): KeyVal<'_>| {
|
||||
let value = self.parse_profile_kv(user_id, &key, value.to_vec())?;
|
||||
Ok((key, value))
|
||||
})
|
||||
.map(|((_, key), value): KeyVal<'_>| Ok((key, serde_json::from_slice(value)?)))
|
||||
.ignore_err()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user