@@ -116,6 +116,9 @@ jobs:
116116 env :
117117 SUPABASE_URL : ${{ secrets.SUPABASE_URL || secrets.POWERSYNC_SUPABASE_URL }}
118118 SUPABASE_KEY : ${{ secrets.SUPABASE_SERVICE_ROLE_KEY || secrets.POWERSYNC_SUPABASE_SERVICE_ROLE_KEY || secrets.SUPABASE_ANON_KEY || secrets.POWERSYNC_SUPABASE_ANON_KEY }}
119+ SUPABASE_ANON_KEY : ${{ secrets.SUPABASE_ANON_KEY || secrets.POWERSYNC_SUPABASE_ANON_KEY }}
120+ POWERGIT_EMAIL : ${{ secrets.POWERGIT_EMAIL }}
121+ POWERGIT_PASSWORD : ${{ secrets.POWERGIT_PASSWORD }}
119122 JOB_ID : ${{ github.event.inputs.job_id }}
120123 ORG_ID : ${{ github.event.inputs.org }}
121124 REPO_ID : ${{ github.event.inputs.repo }}
@@ -131,25 +134,56 @@ jobs:
131134 }
132135 const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_KEY)
133136 const now = new Date().toISOString()
137+
138+ const isUuid = (value) =>
139+ typeof value === 'string' &&
140+ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value.trim())
141+
134142 const requestedByRaw = (process.env.REQUESTED_BY ?? '').trim()
135- const requestedBy = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(requestedByRaw)
136- ? requestedByRaw
137- : null
138- const payload = {
143+ const requestedBy = isUuid(requestedByRaw) ? requestedByRaw : null
144+
145+ const buildPayload = (requestedByValue) => ({
139146 id: process.env.JOB_ID,
140147 org_id: process.env.ORG_ID,
141148 repo_id: process.env.REPO_ID,
142149 repo_url: process.env.REPO_URL,
143150 status: 'running',
144151 created_at: now,
145152 updated_at: now,
146- requested_by: requestedBy ,
153+ requested_by: requestedByValue ,
147154 source: 'actions',
148155 workflow_url: process.env.WORKFLOW_URL ?? null,
149- }
156+ })
157+
150158 ;(async () => {
151- const { error } = await supabase.from('import_jobs').upsert(payload, { onConflict: 'id' })
152- if (error) throw error
159+ const initial = await supabase.from('import_jobs').upsert(buildPayload(requestedBy), { onConflict: 'id' })
160+ if (!initial.error) return
161+
162+ if (initial.error.code !== '42501') throw initial.error
163+
164+ // RLS fallback: authenticate with a known user and record the job as that user.
165+ const anonKey = (process.env.SUPABASE_ANON_KEY ?? '').trim()
166+ const email = (process.env.POWERGIT_EMAIL ?? '').trim()
167+ const password = (process.env.POWERGIT_PASSWORD ?? '').trim()
168+ if (!anonKey || !email || !password) {
169+ throw initial.error
170+ }
171+
172+ const authed = createClient(process.env.SUPABASE_URL, anonKey, {
173+ auth: { persistSession: false, autoRefreshToken: false },
174+ })
175+ const { data, error: loginError } = await authed.auth.signInWithPassword({ email, password })
176+ if (loginError) throw new Error(`Supabase login failed: ${loginError.message}`)
177+ const userId = data?.user?.id ?? ''
178+ if (!isUuid(userId)) throw new Error('Supabase login did not return a valid user id')
179+
180+ // Use REQUESTED_BY only when it matches the authenticated user, otherwise
181+ // pin the job to the CI user so the insert/update RLS policies pass.
182+ const effectiveRequestedBy = requestedBy && requestedBy === userId ? requestedBy : userId
183+ const retry = await authed
184+ .from('import_jobs')
185+ .upsert(buildPayload(effectiveRequestedBy), { onConflict: 'id' })
186+ if (retry.error) throw retry.error
153187 })().catch((err) => {
154188 console.error('Failed to record import job running', err)
155189 process.exit(1)
@@ -254,6 +288,9 @@ jobs:
254288 env :
255289 SUPABASE_URL : ${{ secrets.SUPABASE_URL || secrets.POWERSYNC_SUPABASE_URL }}
256290 SUPABASE_KEY : ${{ secrets.SUPABASE_SERVICE_ROLE_KEY || secrets.POWERSYNC_SUPABASE_SERVICE_ROLE_KEY || secrets.SUPABASE_ANON_KEY || secrets.POWERSYNC_SUPABASE_ANON_KEY }}
291+ SUPABASE_ANON_KEY : ${{ secrets.SUPABASE_ANON_KEY || secrets.POWERSYNC_SUPABASE_ANON_KEY }}
292+ POWERGIT_EMAIL : ${{ secrets.POWERGIT_EMAIL }}
293+ POWERGIT_PASSWORD : ${{ secrets.POWERGIT_PASSWORD }}
257294 JOB_ID : ${{ github.event.inputs.job_id }}
258295 WORKFLOW_STATUS : ${{ job.status }}
259296 run : |
@@ -267,9 +304,35 @@ jobs:
267304 updated_at: now,
268305 error: status === 'error' ? 'GitHub Actions import failed' : null,
269306 }
307+
308+ const isUuid = (value) =>
309+ typeof value === 'string' &&
310+ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value.trim())
311+
270312 ;(async () => {
271- const { error } = await supabase.from('import_jobs').update(update).eq('id', process.env.JOB_ID)
272- if (error) throw error
313+ const initial = await supabase.from('import_jobs').update(update).eq('id', process.env.JOB_ID)
314+ if (!initial.error) return
315+
316+ if (initial.error.code !== '42501') throw initial.error
317+
318+ // RLS fallback: authenticate with a known user and update the job as that user.
319+ const anonKey = (process.env.SUPABASE_ANON_KEY ?? '').trim()
320+ const email = (process.env.POWERGIT_EMAIL ?? '').trim()
321+ const password = (process.env.POWERGIT_PASSWORD ?? '').trim()
322+ if (!anonKey || !email || !password) {
323+ throw initial.error
324+ }
325+
326+ const authed = createClient(process.env.SUPABASE_URL, anonKey, {
327+ auth: { persistSession: false, autoRefreshToken: false },
328+ })
329+ const { data, error: loginError } = await authed.auth.signInWithPassword({ email, password })
330+ if (loginError) throw new Error(`Supabase login failed: ${loginError.message}`)
331+ const userId = data?.user?.id ?? ''
332+ if (!isUuid(userId)) throw new Error('Supabase login did not return a valid user id')
333+
334+ const retry = await authed.from('import_jobs').update(update).eq('id', process.env.JOB_ID)
335+ if (retry.error) throw retry.error
273336 })().catch((err) => {
274337 console.error('Failed to record import job result', err)
275338 process.exit(1)
0 commit comments