Compare commits
2 Commits
v0.1.79-wi
...
v0.1.81-ma
| Author | SHA1 | Date | |
|---|---|---|---|
| d56c6e3845 | |||
| 574fca633a |
@@ -19,6 +19,8 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
build-linux:
|
build-linux:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
version: ${{ steps.version.outputs.VERSION }}
|
||||||
steps:
|
steps:
|
||||||
- name: Install Node.js 22
|
- name: Install Node.js 22
|
||||||
run: |
|
run: |
|
||||||
@@ -374,3 +376,96 @@ jobs:
|
|||||||
echo Uploading %%~nxf...
|
echo Uploading %%~nxf...
|
||||||
curl -s -X POST -H "Authorization: token %TOKEN%" -H "Content-Type: application/octet-stream" --data-binary "@%%f" "%GITEA_URL%/api/v1/repos/%REPO%/releases/%RELEASE_ID%/assets?name=%%~nxf"
|
curl -s -X POST -H "Authorization: token %TOKEN%" -H "Content-Type: application/octet-stream" --data-binary "@%%f" "%GITEA_URL%/api/v1/repos/%REPO%/releases/%RELEASE_ID%/assets?name=%%~nxf"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
sync-to-github:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [build-linux, build-macos, build-windows]
|
||||||
|
if: gitea.event_name == 'push'
|
||||||
|
env:
|
||||||
|
GH_PAT: ${{ secrets.GH_PAT }}
|
||||||
|
GITHUB_REPO: shadowdao/triple-c
|
||||||
|
steps:
|
||||||
|
- name: Download artifacts from Gitea releases
|
||||||
|
env:
|
||||||
|
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
VERSION: ${{ needs.build-linux.outputs.version }}
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
mkdir -p artifacts
|
||||||
|
|
||||||
|
# Download assets from all 3 platform releases
|
||||||
|
for TAG_SUFFIX in "" "-mac" "-win"; do
|
||||||
|
TAG="v${VERSION}${TAG_SUFFIX}"
|
||||||
|
echo "==> Fetching assets for release ${TAG}..."
|
||||||
|
|
||||||
|
RELEASE_JSON=$(curl -sf \
|
||||||
|
-H "Authorization: token ${TOKEN}" \
|
||||||
|
"${GITEA_URL}/api/v1/repos/${REPO}/releases/tags/${TAG}" 2>/dev/null || echo "{}")
|
||||||
|
|
||||||
|
echo "$RELEASE_JSON" | jq -r '.assets[]? | "\(.name) \(.browser_download_url)"' | while read -r NAME URL; do
|
||||||
|
[ -z "$NAME" ] && continue
|
||||||
|
echo " Downloading ${NAME}..."
|
||||||
|
curl -sfL \
|
||||||
|
-H "Authorization: token ${TOKEN}" \
|
||||||
|
-o "artifacts/${NAME}" \
|
||||||
|
"$URL"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "==> All downloaded artifacts:"
|
||||||
|
ls -la artifacts/
|
||||||
|
|
||||||
|
- name: Create GitHub release and upload artifacts
|
||||||
|
env:
|
||||||
|
VERSION: ${{ needs.build-linux.outputs.version }}
|
||||||
|
COMMIT_SHA: ${{ gitea.sha }}
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
TAG="v${VERSION}"
|
||||||
|
|
||||||
|
echo "==> Creating unified release ${TAG} on GitHub..."
|
||||||
|
|
||||||
|
# Delete existing release if present (idempotent re-runs)
|
||||||
|
EXISTING=$(curl -sf \
|
||||||
|
-H "Authorization: Bearer ${GH_PAT}" \
|
||||||
|
-H "Accept: application/vnd.github+json" \
|
||||||
|
"https://api.github.com/repos/${GITHUB_REPO}/releases/tags/${TAG}" 2>/dev/null || echo "{}")
|
||||||
|
EXISTING_ID=$(echo "$EXISTING" | jq -r '.id // empty')
|
||||||
|
if [ -n "$EXISTING_ID" ]; then
|
||||||
|
echo " Deleting existing GitHub release ${TAG} (id: ${EXISTING_ID})..."
|
||||||
|
curl -sf -X DELETE \
|
||||||
|
-H "Authorization: Bearer ${GH_PAT}" \
|
||||||
|
-H "Accept: application/vnd.github+json" \
|
||||||
|
"https://api.github.com/repos/${GITHUB_REPO}/releases/${EXISTING_ID}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
RESPONSE=$(curl -sf -X POST \
|
||||||
|
-H "Authorization: Bearer ${GH_PAT}" \
|
||||||
|
-H "Accept: application/vnd.github+json" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
"https://api.github.com/repos/${GITHUB_REPO}/releases" \
|
||||||
|
-d "{
|
||||||
|
\"tag_name\": \"${TAG}\",
|
||||||
|
\"name\": \"Triple-C ${TAG}\",
|
||||||
|
\"body\": \"Automated build from commit ${COMMIT_SHA}\n\nIncludes Linux, macOS, and Windows artifacts.\",
|
||||||
|
\"draft\": false,
|
||||||
|
\"prerelease\": false
|
||||||
|
}")
|
||||||
|
|
||||||
|
UPLOAD_URL=$(echo "$RESPONSE" | jq -r '.upload_url' | sed 's/{?name,label}//')
|
||||||
|
echo "==> Upload URL: ${UPLOAD_URL}"
|
||||||
|
|
||||||
|
for file in artifacts/*; do
|
||||||
|
[ -f "$file" ] || continue
|
||||||
|
FILENAME=$(basename "$file")
|
||||||
|
MIME="application/octet-stream"
|
||||||
|
echo "==> Uploading ${FILENAME}..."
|
||||||
|
curl -sf -X POST \
|
||||||
|
-H "Authorization: Bearer ${GH_PAT}" \
|
||||||
|
-H "Accept: application/vnd.github+json" \
|
||||||
|
-H "Content-Type: ${MIME}" \
|
||||||
|
--data-binary "@${file}" \
|
||||||
|
"${UPLOAD_URL}?name=$(python3 -c "import urllib.parse, sys; print(urllib.parse.quote(sys.argv[1]))" "${FILENAME}")"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "==> GitHub release sync complete."
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
name: Sync Release to GitHub
|
name: Sync Release to GitHub
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
workflow_dispatch:
|
||||||
types: [published]
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
sync-release:
|
sync-release:
|
||||||
|
|||||||
@@ -1,7 +1,74 @@
|
|||||||
use tauri::{AppHandle, Emitter, State};
|
use tauri::{AppHandle, Emitter, State};
|
||||||
|
|
||||||
|
use crate::models::{AuthMode, BedrockAuthMethod, Project};
|
||||||
use crate::AppState;
|
use crate::AppState;
|
||||||
|
|
||||||
|
/// Build the command to run in the container terminal.
|
||||||
|
///
|
||||||
|
/// For Bedrock Profile projects, wraps `claude` in a bash script that validates
|
||||||
|
/// the AWS session first. If the SSO session is expired, runs `aws sso login`
|
||||||
|
/// so the user can re-authenticate (the URL is clickable via xterm.js WebLinksAddon).
|
||||||
|
fn build_terminal_cmd(project: &Project, state: &AppState) -> Vec<String> {
|
||||||
|
let is_bedrock_profile = project.auth_mode == AuthMode::Bedrock
|
||||||
|
&& project
|
||||||
|
.bedrock_config
|
||||||
|
.as_ref()
|
||||||
|
.map(|b| b.auth_method == BedrockAuthMethod::Profile)
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
if !is_bedrock_profile {
|
||||||
|
return vec![
|
||||||
|
"claude".to_string(),
|
||||||
|
"--dangerously-skip-permissions".to_string(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve AWS profile: project-level → global settings → "default"
|
||||||
|
let profile = project
|
||||||
|
.bedrock_config
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|b| b.aws_profile.clone())
|
||||||
|
.or_else(|| state.settings_store.get().global_aws.aws_profile.clone())
|
||||||
|
.unwrap_or_else(|| "default".to_string());
|
||||||
|
|
||||||
|
// Build a bash wrapper that validates credentials, re-auths if needed,
|
||||||
|
// then exec's into claude.
|
||||||
|
let script = format!(
|
||||||
|
r#"
|
||||||
|
echo "Validating AWS session for profile '{profile}'..."
|
||||||
|
if aws sts get-caller-identity --profile '{profile}' >/dev/null 2>&1; then
|
||||||
|
echo "AWS session valid."
|
||||||
|
else
|
||||||
|
echo "AWS session expired or invalid."
|
||||||
|
# Check if this profile uses SSO (has sso_start_url configured)
|
||||||
|
if aws configure get sso_start_url --profile '{profile}' >/dev/null 2>&1; then
|
||||||
|
echo "Starting SSO login — click the URL below to authenticate:"
|
||||||
|
echo ""
|
||||||
|
aws sso login --profile '{profile}'
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "SSO login failed or was cancelled. Starting Claude anyway..."
|
||||||
|
echo "You may see authentication errors."
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Profile '{profile}' does not use SSO. Check your AWS credentials."
|
||||||
|
echo "Starting Claude anyway..."
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
exec claude --dangerously-skip-permissions
|
||||||
|
"#,
|
||||||
|
profile = profile
|
||||||
|
);
|
||||||
|
|
||||||
|
vec![
|
||||||
|
"bash".to_string(),
|
||||||
|
"-c".to_string(),
|
||||||
|
script,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn open_terminal_session(
|
pub async fn open_terminal_session(
|
||||||
project_id: String,
|
project_id: String,
|
||||||
@@ -19,10 +86,7 @@ pub async fn open_terminal_session(
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or_else(|| "Container not running".to_string())?;
|
.ok_or_else(|| "Container not running".to_string())?;
|
||||||
|
|
||||||
let cmd = vec![
|
let cmd = build_terminal_cmd(&project, &state);
|
||||||
"claude".to_string(),
|
|
||||||
"--dangerously-skip-permissions".to_string(),
|
|
||||||
];
|
|
||||||
|
|
||||||
let output_event = format!("terminal-output-{}", session_id);
|
let output_event = format!("terminal-output-{}", session_id);
|
||||||
let exit_event = format!("terminal-exit-{}", session_id);
|
let exit_event = format!("terminal-exit-{}", session_id);
|
||||||
|
|||||||
@@ -508,7 +508,7 @@ pub async fn create_container(
|
|||||||
if let Some(ref aws_path) = aws_dir {
|
if let Some(ref aws_path) = aws_dir {
|
||||||
if aws_path.exists() {
|
if aws_path.exists() {
|
||||||
mounts.push(Mount {
|
mounts.push(Mount {
|
||||||
target: Some("/home/claude/.aws".to_string()),
|
target: Some("/tmp/.host-aws".to_string()),
|
||||||
source: Some(aws_path.to_string_lossy().to_string()),
|
source: Some(aws_path.to_string_lossy().to_string()),
|
||||||
typ: Some(MountTypeEnum::BIND),
|
typ: Some(MountTypeEnum::BIND),
|
||||||
read_only: Some(true),
|
read_only: Some(true),
|
||||||
|
|||||||
@@ -73,6 +73,19 @@ su -s /bin/bash claude -c '
|
|||||||
sort -u -o /home/claude/.ssh/known_hosts /home/claude/.ssh/known_hosts
|
sort -u -o /home/claude/.ssh/known_hosts /home/claude/.ssh/known_hosts
|
||||||
'
|
'
|
||||||
|
|
||||||
|
# ── AWS config setup ──────────────────────────────────────────────────────────
|
||||||
|
# Host AWS dir is mounted read-only at /tmp/.host-aws.
|
||||||
|
# Copy to /home/claude/.aws so AWS CLI can write to sso/cache and cli/cache.
|
||||||
|
if [ -d /tmp/.host-aws ]; then
|
||||||
|
rm -rf /home/claude/.aws
|
||||||
|
cp -a /tmp/.host-aws /home/claude/.aws
|
||||||
|
chown -R claude:claude /home/claude/.aws
|
||||||
|
chmod 700 /home/claude/.aws
|
||||||
|
# Ensure writable cache directories exist
|
||||||
|
mkdir -p /home/claude/.aws/sso/cache /home/claude/.aws/cli/cache
|
||||||
|
chown -R claude:claude /home/claude/.aws/sso /home/claude/.aws/cli
|
||||||
|
fi
|
||||||
|
|
||||||
# ── Git credential helper (for HTTPS token) ─────────────────────────────────
|
# ── Git credential helper (for HTTPS token) ─────────────────────────────────
|
||||||
if [ -n "$GIT_TOKEN" ]; then
|
if [ -n "$GIT_TOKEN" ]; then
|
||||||
CRED_FILE="/home/claude/.git-credentials"
|
CRED_FILE="/home/claude/.git-credentials"
|
||||||
|
|||||||
Reference in New Issue
Block a user