diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..fedd669 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,40 @@ +# Node modules +node_modules +**/node_modules + +# Logs +*.log +logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Build outputs +build +dist +out +.next +.cache +.parcel-cache + +# Environment files +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# OS files +.DS_Store +Thumbs.db + +# IDE / Editor folders +.vscode +.idea +*.sublime-workspace +*.sublime-project + +# Temporary files +*.swp +*.bak +*.tmp diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..42459d9 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,130 @@ +--- +kind: pipeline +type: docker +name: default + +platform: + os: linux + arch: arm64 + +workspace: + path: /drone/src + +volumes: + - name: dockersock + host: + path: /var/run/docker.sock + +steps: + - name: fetch-tags + image: docker:24 + volumes: + - name: dockersock + path: /var/run/docker.sock + commands: + - apk add --no-cache git + - git fetch --tags + - | + # Get latest Git tag and trim newline + LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null | tr -d '\n') + echo "Latest Git tag fetched: $LATEST_TAG" + + # Save to file for downstream steps + echo "$LATEST_TAG" > /drone/src/LATEST_TAG.txt + + # Read back for verification + IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n') + echo "Image tag read from file: $IMAGE_TAG" + + # Validate + if [ -z "$IMAGE_TAG" ]; then + echo "❌ No git tags found! Cannot continue." + exit 1 + fi + + - name: check-remote-image + image: docker:24 + volumes: + - name: dockersock + path: /var/run/docker.sock + commands: + - IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n') + + - echo "Checking if apps/blog:$IMAGE_TAG exists on remote Docker..." + - echo "Existing Docker tags for apps/blog:" + - docker images --format "{{.Repository}}:{{.Tag}}" | grep "^apps/blog" || echo "(none)" + - | + if docker image inspect apps/blog:$IMAGE_TAG > /dev/null 2>&1; then + echo "✅ Docker image apps/blog:$IMAGE_TAG already exists — skipping build" + exit 78 + else + echo "⚙️ Docker image apps/blog:$IMAGE_TAG not found — proceeding to build..." + fi + + - name: build-image + image: docker:24 + volumes: + - name: dockersock + path: /var/run/docker.sock + commands: + - IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n') + + - echo "🔨 Building Docker image apps/blog:$IMAGE_TAG ..." + - docker build --network=host -t apps/blog:$IMAGE_TAG -t apps/blog:latest /drone/src + + - name: push-image + image: docker:24 + environment: + REGISTRY_HOST: + from_secret: REGISTRY_HOST + REGISTRY_USER: + from_secret: REGISTRY_USER + REGISTRY_PASS: + from_secret: REGISTRY_PASS + volumes: + - name: dockersock + path: /var/run/docker.sock + commands: + - IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n') + + - echo "🔑 Logging into registry $REGISTRY_HOST ..." + - echo "$REGISTRY_PASS" | docker login $REGISTRY_HOST -u "$REGISTRY_USER" --password-stdin + - echo "🏷️ Tagging images with registry prefix..." + - docker tag apps/blog:$IMAGE_TAG $REGISTRY_HOST/apps/blog:$IMAGE_TAG + - docker tag apps/blog:$IMAGE_TAG $REGISTRY_HOST/apps/blog:latest + - echo "📤 Pushing apps/blog:$IMAGE_TAG ..." + - docker push $REGISTRY_HOST/apps/blog:$IMAGE_TAG + - echo "📤 Pushing apps/blog:latest ..." + - docker push $REGISTRY_HOST/apps/blog:latest + + - name: stop-old + image: docker:24 + volumes: + - name: dockersock + path: /var/run/docker.sock + commands: + - echo "🛑 Stopping old container..." + - docker rm -f blog || true + + - name: run-container + image: docker:24 + volumes: + - name: dockersock + path: /var/run/docker.sock + commands: + - IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n') + + - echo "🚀 Starting container apps/blog:$IMAGE_TAG ..." + - | + docker run -d \ + --name blog \ + -p 3002:3000 \ + -e NODE_ENV=production \ + --restart always \ + apps/blog:$IMAGE_TAG + +# Trigger rules +trigger: + event: + - tag + - custom diff --git a/.gitignore b/.gitignore index 065d07b..a1a5c89 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,10 @@ # dependencies node_modules +# React Router +.react-router +build + # misc .DS_Store dist diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..70138f6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,33 @@ +# Stage 1: Build +FROM node:20-alpine AS builder + +# Set working directory +WORKDIR /app + +# Copy package.json and package-lock.json (or yarn.lock) +COPY package*.json ./ + +# Install dependencies +RUN npm ci + +# Copy the rest of the app +COPY . . + +# Build the app (React/Next/etc.) +RUN npm run build + +# Stage 2: Production image +FROM node:20-alpine + +WORKDIR /app + +# Copy only build output and dependencies +COPY --from=builder /app/package*.json ./ +COPY --from=builder /app/node_modules ./node_modules +COPY --from=builder /app/build ./build + +# Expose port +EXPOSE 3000 + +# Default command +CMD ["npm", "start"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..1556619 --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +# Material UI - React Router example in TypeScript + +## How to use + +Download the example [or clone the repo](https://github.com/mui/material-ui): + + + +```bash +curl https://codeload.github.com/mui/material-ui/tar.gz/master | tar -xz --strip=2 material-ui-master/examples/material-ui-react-router-ts +cd material-ui-react-router-ts +``` + +Install it and run: + +```bash +npm install +npm run dev +``` + +or: + + + +[![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/github/mui/material-ui/tree/master/examples/material-ui-react-router-ts) + +[![Edit on StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/mui/material-ui/tree/master/examples/material-ui-react-router-ts) + +## The idea behind the example + + + +This example demonstrates how you can use Material UI with [React Router](https://reactrouter.com/) in [TypeScript](https://github.com/Microsoft/TypeScript). +It includes `@mui/material` and its peer dependencies, including [Emotion](https://emotion.sh/docs/introduction), the default style engine in Material UI. + +## What's next? + + + +You now have a working example project. +You can head back to the documentation and continue by browsing the [templates](https://mui.com/material-ui/getting-started/templates/) section.