mirror of
https://github.com/Sonny93/my-links.git
synced 2025-12-09 07:03:25 +00:00
ci: create docker push only workflow
and change default behaviour: deploy when tag is created instead
This commit is contained in:
20
.github/workflows/CD.yml
vendored
20
.github/workflows/CD.yml
vendored
@@ -1,32 +1,34 @@
|
|||||||
name: CD
|
name: CI/CD prod
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
release:
|
||||||
branches:
|
types: published
|
||||||
- main
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
push_image_to_docker_hub:
|
push_image_to_docker_hub:
|
||||||
name: Push Docker image to Docker Hub
|
name: Build and push image to Docker Hub
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repo
|
- name: Checkout the repo
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: docker_meta
|
id: docker_meta
|
||||||
uses: docker/metadata-action@v5.0.0
|
uses: docker/metadata-action@v5.5.1
|
||||||
with:
|
with:
|
||||||
images: sonny93/my-links
|
images: sonny93/my-links
|
||||||
flavor: latest=true
|
flavor: latest=true
|
||||||
tags: |
|
tags: |
|
||||||
type=sha,prefix=
|
type=semver,pattern={{version}}
|
||||||
|
|
||||||
- name: Login to DockerHub
|
- name: Login to DockerHub
|
||||||
uses: docker/login-action@v3.0.0
|
uses: docker/login-action@v3.1.0
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@v5.0.0
|
uses: docker/build-push-action@v5.3.0
|
||||||
with:
|
with:
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
context: .
|
context: .
|
||||||
|
|||||||
16
.release-it.json
Normal file
16
.release-it.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"hooks": {
|
||||||
|
"before:init": [
|
||||||
|
"npm run lint"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"git": {
|
||||||
|
"commitMessage": "chore: release v${version}"
|
||||||
|
},
|
||||||
|
"github": {
|
||||||
|
"release": true
|
||||||
|
},
|
||||||
|
"npm": {
|
||||||
|
"publish": false
|
||||||
|
}
|
||||||
|
}
|
||||||
12
Makefile
12
Makefile
@@ -1,8 +1,14 @@
|
|||||||
db:
|
db:
|
||||||
docker compose -f dev.docker-compose.yml up -d
|
docker compose -f dev.docker-compose.yml up -d --wait
|
||||||
|
|
||||||
dev:
|
dev: db
|
||||||
|
npx prisma migrate deploy
|
||||||
|
npx prisma generate
|
||||||
npm run dev
|
npm run dev
|
||||||
|
|
||||||
|
release:
|
||||||
|
npm run release
|
||||||
|
|
||||||
prod:
|
prod:
|
||||||
docker compose up -d --build
|
-docker network create mylinks_app
|
||||||
|
docker compose up -d --build --wait
|
||||||
|
|||||||
@@ -1,25 +1,27 @@
|
|||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
mariadb:
|
mysqldb:
|
||||||
container_name: mariadb
|
|
||||||
image: mysql:latest
|
image: mysql:latest
|
||||||
restart: always
|
restart: always
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
ports:
|
ports:
|
||||||
- '3306:3306'
|
- '3306:3306'
|
||||||
|
healthcheck:
|
||||||
|
test: mysqladmin ping -h 127.0.0.1 -u $$MYSQL_USER --password=$$MYSQL_PASSWORD
|
||||||
|
start_period: 5s
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 55
|
||||||
|
|
||||||
phpmyadmin:
|
phpmyadmin:
|
||||||
image: phpmyadmin:5
|
image: phpmyadmin:5
|
||||||
container_name: phpmyadmin
|
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
- PMA_HOST=mariadb
|
- PMA_HOST=mysqldb
|
||||||
- PMA_PORT=3306
|
- PMA_PORT=3306
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
ports:
|
ports:
|
||||||
- '8080:80'
|
- '8080:80'
|
||||||
depends_on:
|
depends_on:
|
||||||
- mariadb
|
- mysqldb
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
version: '3.8'
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
mylinks_app:
|
mylinks_app:
|
||||||
external: true
|
external: true
|
||||||
@@ -14,8 +12,16 @@ services:
|
|||||||
- '127.0.0.1:3000:3000'
|
- '127.0.0.1:3000:3000'
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
|
environment:
|
||||||
|
- DATABASE_URL=mysql://${MYSQL_USER}:${MYSQL_PASSWORD}@mylinks_db:3306/${MYSQL_DATABASE}
|
||||||
networks:
|
networks:
|
||||||
- mylinks_app
|
- mylinks_app
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
[
|
||||||
|
'CMD-SHELL',
|
||||||
|
'wget --spider --tries=1 --no-verbose http://0.0.0.0:3000',
|
||||||
|
]
|
||||||
depends_on:
|
depends_on:
|
||||||
mylinks_db:
|
mylinks_db:
|
||||||
condition: service_started
|
condition: service_started
|
||||||
@@ -28,5 +34,11 @@ services:
|
|||||||
- ./docker-config/mysql-dev-init.sql:/docker-entrypoint-initdb.d/init.sql
|
- ./docker-config/mysql-dev-init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
|
healthcheck:
|
||||||
|
test: mysqladmin ping -h 127.0.0.1 -u $$MYSQL_USER --password=$$MYSQL_PASSWORD
|
||||||
|
start_period: 5s
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 55
|
||||||
networks:
|
networks:
|
||||||
- mylinks_app
|
- mylinks_app
|
||||||
|
|||||||
3666
package-lock.json
generated
3666
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "my-links",
|
"name": "my-links",
|
||||||
|
"version": "0.0.0",
|
||||||
"description": "MyLinks is a free and open source software, that lets you manage your bookmarks in an intuitive interface",
|
"description": "MyLinks is a free and open source software, that lets you manage your bookmarks in an intuitive interface",
|
||||||
"private": true,
|
"private": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
"postbuild": "next-sitemap",
|
"postbuild": "next-sitemap",
|
||||||
"prepare": "husky install"
|
"prepare": "husky install",
|
||||||
|
"release": "release-it"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ducanh2912/next-pwa": "^10.0.0",
|
"@ducanh2912/next-pwa": "^10.0.0",
|
||||||
@@ -53,6 +55,7 @@
|
|||||||
"husky": "^8.0.3",
|
"husky": "^8.0.3",
|
||||||
"lint-staged": "^15.2.0",
|
"lint-staged": "^15.2.0",
|
||||||
"prisma": "^5.7.0",
|
"prisma": "^5.7.0",
|
||||||
|
"release-it": "^17.1.1",
|
||||||
"typescript": "5.3.3"
|
"typescript": "5.3.3"
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
|
|||||||
24
src/components/ExternalLink.tsx
Normal file
24
src/components/ExternalLink.tsx
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import Link, { LinkProps } from 'next/link';
|
||||||
|
import { CSSProperties, ReactNode } from 'react';
|
||||||
|
|
||||||
|
export default function ExternalLink({
|
||||||
|
children,
|
||||||
|
title,
|
||||||
|
...props
|
||||||
|
}: LinkProps & {
|
||||||
|
children: ReactNode;
|
||||||
|
style?: CSSProperties;
|
||||||
|
title?: string;
|
||||||
|
className?: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
target='_blank'
|
||||||
|
rel='noreferrer'
|
||||||
|
title={title}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
|
import ExternalLink from 'components/ExternalLink';
|
||||||
import PATHS from 'constants/paths';
|
import PATHS from 'constants/paths';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import LinkTag from 'next/link';
|
import LinkTag from 'next/link';
|
||||||
|
import packageJson from '../../../package.json';
|
||||||
import styles from './footer.module.scss';
|
import styles from './footer.module.scss';
|
||||||
|
|
||||||
export default function Footer() {
|
export default function Footer() {
|
||||||
@@ -8,33 +10,23 @@ export default function Footer() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className={styles['footer']}>
|
<footer className={styles['footer']}>
|
||||||
<div className='top'>
|
<div className='row'>
|
||||||
<LinkTag href={PATHS.PRIVACY}>{t('common:privacy')}</LinkTag>
|
<LinkTag href={PATHS.PRIVACY}>{t('common:privacy')}</LinkTag>
|
||||||
{' • '}
|
{' • '}
|
||||||
<LinkTag href={PATHS.TERMS}>{t('common:terms')}</LinkTag>
|
<LinkTag href={PATHS.TERMS}>{t('common:terms')}</LinkTag>
|
||||||
|
{' • '}
|
||||||
|
<ExternalLink href={PATHS.EXTENSION}>Extension</ExternalLink>
|
||||||
</div>
|
</div>
|
||||||
<div className='bottom'>
|
<div className='row'>
|
||||||
{t('common:footer.made_by')}{' '}
|
{t('common:footer.made_by')}{' '}
|
||||||
<LinkTag
|
<ExternalLink href={PATHS.AUTHOR}>Sonny</ExternalLink>
|
||||||
href={PATHS.AUTHOR}
|
|
||||||
target='_blank'
|
|
||||||
>
|
|
||||||
Sonny
|
|
||||||
</LinkTag>
|
|
||||||
{' • '}
|
{' • '}
|
||||||
<LinkTag
|
<span>
|
||||||
href={PATHS.REPO_GITHUB}
|
Version:{' '}
|
||||||
target='_blank'
|
<ExternalLink href={PATHS.REPO_GITHUB}>
|
||||||
>
|
{packageJson.version}
|
||||||
Github
|
</ExternalLink>
|
||||||
</LinkTag>
|
</span>
|
||||||
{' • '}
|
|
||||||
<LinkTag
|
|
||||||
href={PATHS.EXTENSION}
|
|
||||||
target='_blank'
|
|
||||||
>
|
|
||||||
Extension
|
|
||||||
</LinkTag>
|
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
import Footer from 'components/Footer/Footer';
|
||||||
import Navbar from 'components/Navbar/Navbar';
|
import Navbar from 'components/Navbar/Navbar';
|
||||||
import PageTransition from 'components/PageTransition';
|
import PageTransition from 'components/PageTransition';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
@@ -62,6 +63,7 @@ export default function Privacy() {
|
|||||||
<p>{t('privacy:footer.changes')}</p>
|
<p>{t('privacy:footer.changes')}</p>
|
||||||
<p>{t('privacy:footer.thanks')}</p>
|
<p>{t('privacy:footer.thanks')}</p>
|
||||||
</main>
|
</main>
|
||||||
|
<Footer />
|
||||||
</PageTransition>
|
</PageTransition>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
import Footer from 'components/Footer/Footer';
|
||||||
import Navbar from 'components/Navbar/Navbar';
|
import Navbar from 'components/Navbar/Navbar';
|
||||||
import PageTransition from 'components/PageTransition';
|
import PageTransition from 'components/PageTransition';
|
||||||
import PATHS from 'constants/paths';
|
import PATHS from 'constants/paths';
|
||||||
@@ -71,6 +72,7 @@ export default function Terms() {
|
|||||||
<p>{t('terms:footer.changes')}</p>
|
<p>{t('terms:footer.changes')}</p>
|
||||||
<p>{t('terms:footer.thanks')}</p>
|
<p>{t('terms:footer.thanks')}</p>
|
||||||
</main>
|
</main>
|
||||||
|
<Footer />
|
||||||
</PageTransition>
|
</PageTransition>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user