gitea workflows
Some checks failed
Build & Push Docker Images / build (push) Failing after 30s

This commit is contained in:
Thomas Faour 2025-08-10 13:21:21 -04:00
parent 507de383cf
commit 629ff78af8
5 changed files with 140 additions and 22 deletions

View File

@ -0,0 +1,59 @@
name: Build & Push Docker Images
on:
push:
branches: ["main", "master"]
tags: ["v*.*.*"]
pull_request:
branches: ["main", "master"]
env:
REGISTRY: ${REGISTRY:-registry.local} # Override via repository/organization secret or .env in runner
IMAGE_NAMESPACE: ${IMAGE_NAMESPACE:-youruser} # Your Gitea username/org
BACKEND_IMAGE: imap-client-backend
FRONTEND_IMAGE: imap-client-frontend
jobs:
build:
runs-on: docker
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Prepare tags
id: meta
run: |
SHA_TAG=sha-${GITHUB_SHA::7}
echo "sha_tag=$SHA_TAG" >> $GITHUB_OUTPUT
if [[ "$GITHUB_REF" == refs/heads/main || "$GITHUB_REF" == refs/heads/master ]]; then
echo "latest_tag=latest" >> $GITHUB_OUTPUT
fi
if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
VERSION_TAG=${GITHUB_REF#refs/tags/}
echo "version_tag=$VERSION_TAG" >> $GITHUB_OUTPUT
fi
- name: Login to registry
run: |
echo "${{ secrets.CR_PASSWORD }}" | docker login "${REGISTRY}" -u "${{ secrets.CR_USERNAME }}" --password-stdin
- name: Build backend
run: |
docker build -t ${REGISTRY}/${IMAGE_NAMESPACE}/${BACKEND_IMAGE}:${{ steps.meta.outputs.sha_tag }} ./backend
if [ -n "${{ steps.meta.outputs.latest_tag }}" ]; then docker tag ${REGISTRY}/${IMAGE_NAMESPACE}/${BACKEND_IMAGE}:${{ steps.meta.outputs.sha_tag }} ${REGISTRY}/${IMAGE_NAMESPACE}/${BACKEND_IMAGE}:latest; fi
if [ -n "${{ steps.meta.outputs.version_tag }}" ]; then docker tag ${REGISTRY}/${IMAGE_NAMESPACE}/${BACKEND_IMAGE}:${{ steps.meta.outputs.sha_tag }} ${REGISTRY}/${IMAGE_NAMESPACE}/${BACKEND_IMAGE}:${{ steps.meta.outputs.version_tag }}; fi
- name: Build frontend
run: |
docker build -t ${REGISTRY}/${IMAGE_NAMESPACE}/${FRONTEND_IMAGE}:${{ steps.meta.outputs.sha_tag }} ./frontend
if [ -n "${{ steps.meta.outputs.latest_tag }}" ]; then docker tag ${REGISTRY}/${IMAGE_NAMESPACE}/${FRONTEND_IMAGE}:${{ steps.meta.outputs.sha_tag }} ${REGISTRY}/${IMAGE_NAMESPACE}/${FRONTEND_IMAGE}:latest; fi
if [ -n "${{ steps.meta.outputs.version_tag }}" ]; then docker tag ${REGISTRY}/${IMAGE_NAMESPACE}/${FRONTEND_IMAGE}:${{ steps.meta.outputs.sha_tag }} ${REGISTRY}/${IMAGE_NAMESPACE}/${FRONTEND_IMAGE}:${{ steps.meta.outputs.version_tag }}; fi
- name: Push images
if: github.event_name != 'pull_request'
run: |
for IMG in ${BACKEND_IMAGE} ${FRONTEND_IMAGE}; do
docker push ${REGISTRY}/${IMAGE_NAMESPACE}/${IMG}:${{ steps.meta.outputs.sha_tag }}
if [ -n "${{ steps.meta.outputs.latest_tag }}" ]; then docker push ${REGISTRY}/${IMAGE_NAMESPACE}/${IMG}:latest; fi
if [ -n "${{ steps.meta.outputs.version_tag }}" ]; then docker push ${REGISTRY}/${IMAGE_NAMESPACE}/${IMG}:${{ steps.meta.outputs.version_tag }}; fi
done

View File

@ -22,16 +22,36 @@ app.use(session({
}));
/* OIDC setup (lazy) */
type OidcConfig = {
issuer:string;
clientId:string;
clientSecret:string;
redirectUri:string;
providerName:string;
};
function loadOidcConfig():OidcConfig {
const issuer = process.env.OIDC_ISSUER || '';
const clientId = process.env.OIDC_CLIENT_ID || '';
const clientSecret = process.env.OIDC_CLIENT_SECRET || '';
const redirectUri = process.env.OIDC_REDIRECT_URI || '';
const providerName = process.env.OIDC_PROVIDER || 'Identity Provider';
if (!issuer || !clientId || !clientSecret || !redirectUri) {
throw new Error('OIDC env vars incomplete (OIDC_ISSUER / OIDC_CLIENT_ID / OIDC_CLIENT_SECRET / OIDC_REDIRECT_URI)');
}
if (clientSecret.includes('replace-with-real-secret')) {
log.warn('Using placeholder OIDC_CLIENT_SECRET replace before production.');
}
return { issuer, clientId, clientSecret, redirectUri, providerName };
}
const oidcCfg = loadOidcConfig();
let oidcClient: Client | null = null;
async function getClient() {
if (oidcClient) return oidcClient;
const issuerUrl = process.env.OIDC_ISSUER;
if (!issuerUrl) throw new Error('OIDC_ISSUER missing');
const issuer = await Issuer.discover(issuerUrl);
const issuer = await Issuer.discover(oidcCfg.issuer);
oidcClient = new issuer.Client({
client_id: process.env.OIDC_CLIENT_ID!,
client_secret: process.env.OIDC_CLIENT_SECRET!,
redirect_uris: [process.env.OIDC_REDIRECT_URI!],
client_id: oidcCfg.clientId,
client_secret: oidcCfg.clientSecret,
redirect_uris: [oidcCfg.redirectUri],
response_types: ['code']
});
return oidcClient;
@ -61,7 +81,7 @@ app.get('/api/auth/callback', async (req,res)=>{
const params = client.callbackParams(req);
const saved = (req.session as any).oidc;
if (!saved || params.state !== saved.state) return res.status(400).send('Bad state');
const tokenSet = await client.callback(process.env.OIDC_REDIRECT_URI!, params, { state: saved.state, nonce: saved.nonce });
const tokenSet = await client.callback(oidcCfg.redirectUri, params, { state: saved.state, nonce: saved.nonce });
const claims = tokenSet.claims();
const user = upsertUser(claims.sub, claims.email);
(req.session as any).userId = user.id;
@ -149,5 +169,24 @@ app.post('/api/sync/:accountId', requireAuth, (req,res)=>{
res.json({ started:true });
});
app.get('/api/auth/config', (_req,res)=>{
res.json({
issuer: oidcCfg.issuer,
redirectUri: oidcCfg.redirectUri,
provider: oidcCfg.providerName,
clientIdPreview: oidcCfg.clientId ? oidcCfg.clientId.slice(0,4)+'...' : ''
});
});
const port = Number(process.env.PORT||8080);
app.listen(port, ()=> log.info({port}, 'listening'));
app.listen(port, ()=> {
log.info({
oidc: {
issuer: oidcCfg.issuer,
redirect: oidcCfg.redirectUri,
provider: oidcCfg.providerName,
clientIdLen: oidcCfg.clientId.length
},
port
}, 'listening');
});

View File

@ -1,32 +1,45 @@
version: "3.9"
services:
backend:
image: ${REGISTRY:-registry.local}/${IMAGE_NAMESPACE:-youruser}/imap-client-backend:latest
build:
context: ./backend
dockerfile: Dockerfile
# You can also add: env_file: .env (uncomment if you create a .env)
environment:
- IMAP_CLIENT_DB_PATH=/data/app.db
- NODE_ENV=production
- PORT=8080
- OIDC_ISSUER=https://auth.thumeit.com/.well-known/openid-configuration
- OIDC_CLIENT_ID=changeme
- OIDC_CLIENT_SECRET=changeme
- OIDC_REDIRECT_URI=http://localhost:8080/api/auth/callback
- SESSION_SECRET=dev_change_me
- FRONTEND_ORIGIN=http://localhost:5173
- OIDC_PROVIDER=AuthServer
# Optional: BING_MKT=en-US (frontend will default to en-US if unset)
IMAP_CLIENT_DB_PATH: /data/app.db
NODE_ENV: production
PORT: 8080
# OIDC (override in .env for production)
OIDC_ISSUER: ${OIDC_ISSUER:-https://auth.thumeit.com/.well-known/openid-configuration}
OIDC_CLIENT_ID: ${OIDC_CLIENT_ID:-imap_client}
OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET:-replace-with-real-secret}
OIDC_REDIRECT_URI: ${OIDC_REDIRECT_URI:-http://localhost:8080/api/auth/callback}
OIDC_PROVIDER: ${OIDC_PROVIDER:-AuthServer}
# Session secret (generate: openssl rand -base64 48)
SESSION_SECRET: ${SESSION_SECRET:-change-this-session-secret}
# Frontend origin(s) comma-separated for CORS
FRONTEND_ORIGIN: ${FRONTEND_ORIGIN:-http://localhost:5173}
# Optional future: BING_MKT backend side (frontend uses VITE_BING_MKT)
volumes:
- backend_data:/data
ports:
- "8080:8080"
frontend:
image: ${REGISTRY:-registry.local}/${IMAGE_NAMESPACE:-youruser}/imap-client-frontend:latest
build:
context: ./frontend
dockerfile: Dockerfile
args:
VITE_API_BASE: ${VITE_API_BASE:-http://localhost:8080}
OIDC_PROVIDER: ${OIDC_PROVIDER:-AuthServer}
VITE_BING_MKT: ${VITE_BING_MKT:-en-US}
VITE_BING_DISABLE: ${VITE_BING_DISABLE:-0}
environment:
- VITE_API_BASE=http://localhost:8080
- OIDC_PROVIDER=AuthServer
VITE_API_BASE: ${VITE_API_BASE:-http://localhost:8080}
OIDC_PROVIDER: ${OIDC_PROVIDER:-AuthServer}
VITE_BING_MKT: ${VITE_BING_MKT:-en-US}
VITE_BING_DISABLE: ${VITE_BING_DISABLE:-0}
ports:
- "5173:80"
depends_on:

View File

@ -5,7 +5,13 @@ RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi && npm instal
COPY index.html vite.config.ts tsconfig.json ./
COPY src ./src
ARG VITE_API_BASE
ARG OIDC_PROVIDER
ARG VITE_BING_MKT
ARG VITE_BING_DISABLE
ENV VITE_API_BASE=$VITE_API_BASE
ENV OIDC_PROVIDER=$OIDC_PROVIDER
ENV VITE_BING_MKT=$VITE_BING_MKT
ENV VITE_BING_DISABLE=$VITE_BING_DISABLE
RUN npm run build
FROM nginx:1.27-alpine

View File

@ -5,6 +5,7 @@ export default defineConfig({
plugins:[react()],
define: {
__API_BASE__: JSON.stringify(process.env.VITE_API_BASE || 'http://localhost:8080'),
__OIDC_PROVIDER__: JSON.stringify(process.env.OIDC_PROVIDER || process.env.VITE_OIDC_PROVIDER || 'Identity Provider')
__OIDC_PROVIDER__: JSON.stringify(process.env.OIDC_PROVIDER || process.env.VITE_OIDC_PROVIDER || 'Identity Provider'),
__PROVIDER_NAME__: JSON.stringify(process.env.PROVIDER_NAME || 'Default Provider')
}
});