fix(gitea-bot): add write:organization scope so bot can create repos
Without this the bot PAT 403s on POST /orgs/{org}/repos, which is
the single most important operation — creating new project repos
inside the workspace's Gitea org.
Made-with: Cursor
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { toast } from "sonner";
|
||||
import { JM } from "./modal-theme";
|
||||
import { SetupHeader, FieldLabel, TextInput, PrimaryButton, type SetupProps } from "./setup-shared";
|
||||
|
||||
const HOSTING_OPTIONS = [
|
||||
@@ -70,7 +71,7 @@ export function MigrateSetup({ workspace, onClose, onBack }: SetupProps) {
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ padding: "32px 36px 36px" }}>
|
||||
<div style={{ padding: 28 }}>
|
||||
<SetupHeader
|
||||
icon="⇢" label="Migrate Product" tagline="Move an existing product"
|
||||
accent="#4a2a5a" onBack={onBack} onClose={onClose}
|
||||
@@ -86,7 +87,7 @@ export function MigrateSetup({ workspace, onClose, onBack }: SetupProps) {
|
||||
|
||||
<FieldLabel>
|
||||
Repository URL{" "}
|
||||
<span style={{ color: "#b5b0a6", fontWeight: 400 }}>(recommended)</span>
|
||||
<span style={{ color: JM.muted, fontWeight: 400 }}>(recommended)</span>
|
||||
</FieldLabel>
|
||||
<TextInput
|
||||
value={repoUrl}
|
||||
@@ -96,7 +97,7 @@ export function MigrateSetup({ workspace, onClose, onBack }: SetupProps) {
|
||||
|
||||
<FieldLabel>
|
||||
Live URL{" "}
|
||||
<span style={{ color: "#b5b0a6", fontWeight: 400 }}>(optional)</span>
|
||||
<span style={{ color: JM.muted, fontWeight: 400 }}>(optional)</span>
|
||||
</FieldLabel>
|
||||
<TextInput
|
||||
value={liveUrl}
|
||||
@@ -111,14 +112,16 @@ export function MigrateSetup({ workspace, onClose, onBack }: SetupProps) {
|
||||
value={hosting}
|
||||
onChange={e => setHosting(e.target.value)}
|
||||
style={{
|
||||
width: "100%", padding: "11px 14px", marginBottom: 16,
|
||||
borderRadius: 8, border: "1px solid #e0dcd4",
|
||||
background: "#faf8f5", fontSize: "0.88rem",
|
||||
fontFamily: "var(--font-inter), ui-sans-serif, sans-serif", color: hosting ? "#1a1a1a" : "#a09a90",
|
||||
width: "100%", padding: "10px 13px", marginBottom: 16,
|
||||
borderRadius: 8, border: `1px solid ${JM.border}`,
|
||||
background: JM.inputBg, fontSize: 13,
|
||||
fontFamily: JM.fontSans, color: hosting ? JM.ink : JM.muted,
|
||||
outline: "none", boxSizing: "border-box", appearance: "none",
|
||||
backgroundImage: `url("data:image/svg+xml,%3Csvg width='10' height='6' viewBox='0 0 10 6' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23a09a90' strokeWidth='1.5' strokeLinecap='round' strokeLinejoin='round'/%3E%3C/svg%3E")`,
|
||||
backgroundImage: `url("data:image/svg+xml,%3Csvg width='10' height='6' viewBox='0 0 10 6' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%239CA3AF' strokeWidth='1.5' strokeLinecap='round' strokeLinejoin='round'/%3E%3C/svg%3E")`,
|
||||
backgroundRepeat: "no-repeat", backgroundPosition: "right 12px center",
|
||||
}}
|
||||
onFocus={e => (e.currentTarget.style.borderColor = JM.indigo)}
|
||||
onBlur={e => (e.currentTarget.style.borderColor = JM.border)}
|
||||
>
|
||||
{HOSTING_OPTIONS.map(o => (
|
||||
<option key={o.value} value={o.value}>{o.label}</option>
|
||||
@@ -127,7 +130,7 @@ export function MigrateSetup({ workspace, onClose, onBack }: SetupProps) {
|
||||
</div>
|
||||
<div>
|
||||
<FieldLabel>
|
||||
PAT{" "}<span style={{ color: "#b5b0a6", fontWeight: 400 }}>(private repos)</span>
|
||||
PAT{" "}<span style={{ color: JM.muted, fontWeight: 400 }}>(private repos)</span>
|
||||
</FieldLabel>
|
||||
<input
|
||||
type="password"
|
||||
@@ -135,20 +138,24 @@ export function MigrateSetup({ workspace, onClose, onBack }: SetupProps) {
|
||||
onChange={e => setPat(e.target.value)}
|
||||
placeholder="ghp_…"
|
||||
style={{
|
||||
width: "100%", padding: "11px 14px", marginBottom: 16,
|
||||
borderRadius: 8, border: "1px solid #e0dcd4",
|
||||
background: "#faf8f5", fontSize: "0.9rem",
|
||||
fontFamily: "var(--font-inter), ui-sans-serif, sans-serif", color: "#1a1a1a",
|
||||
width: "100%", padding: "10px 13px", marginBottom: 16,
|
||||
borderRadius: 8, border: `1px solid ${JM.border}`,
|
||||
background: JM.inputBg, fontSize: 14,
|
||||
fontFamily: JM.fontSans, color: JM.ink,
|
||||
outline: "none", boxSizing: "border-box",
|
||||
}}
|
||||
onFocus={e => (e.currentTarget.style.borderColor = "#1a1a1a")}
|
||||
onBlur={e => (e.currentTarget.style.borderColor = "#e0dcd4")}
|
||||
onFocus={e => (e.currentTarget.style.borderColor = JM.indigo)}
|
||||
onBlur={e => (e.currentTarget.style.borderColor = JM.border)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ fontSize: "0.75rem", color: "#a09a90", marginBottom: 20, lineHeight: 1.5, padding: "12px 14px", background: "#faf8f5", borderRadius: 8, border: "1px solid #f0ece4" }}>
|
||||
<strong style={{ color: "#4a2a5a" }}>Non-destructive.</strong> Vibn builds a full audit and migration plan. Your existing product stays live throughout the entire migration process.
|
||||
<div style={{
|
||||
fontSize: 12, color: JM.mid, marginBottom: 20, lineHeight: 1.5,
|
||||
padding: "12px 14px", background: JM.cream, borderRadius: 8,
|
||||
border: `1px solid ${JM.border}`, fontFamily: JM.fontSans,
|
||||
}}>
|
||||
<strong style={{ color: "#5B21B6" }}>Non-destructive.</strong> Vibn builds a full audit and migration plan. Your existing product stays live throughout the entire migration process.
|
||||
</div>
|
||||
|
||||
<PrimaryButton onClick={handleCreate} disabled={!canCreate} loading={loading}>
|
||||
|
||||
Reference in New Issue
Block a user