refactor(docker): make builds more repeatable
Remove things like build date and sha from app to improve build repeatability and caching.
This commit is contained in:
parent
c8e40204e6
commit
0624ab576d
|
@ -28,10 +28,18 @@ jobs:
|
|||
- name: Checkout
|
||||
uses: actions/checkout@v2.3.3
|
||||
|
||||
- name: Repo metadata
|
||||
id: repo
|
||||
uses: actions/github-script@v3.0.0
|
||||
with:
|
||||
script: |
|
||||
const repo = await github.repos.get(context.repo)
|
||||
return repo.data
|
||||
|
||||
- name: Prepare
|
||||
id: prep
|
||||
run: |
|
||||
echo ::set-output name=build-date::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
||||
echo ::set-output name=created::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1.0.1
|
||||
|
@ -84,11 +92,16 @@ jobs:
|
|||
file: ./${{ matrix.dockerfile}}
|
||||
platforms: ${{ steps.platforms.outputs.result }}
|
||||
tags: ${{ matrix.docker-image }}:${{ github.sha }}
|
||||
labels: |
|
||||
org.opencontainers.image.title=${{ fromJson(steps.repo.outputs.result).name }}
|
||||
org.opencontainers.image.description=${{ fromJson(steps.repo.outputs.result).description }}
|
||||
org.opencontainers.image.url=${{ fromJson(steps.repo.outputs.result).html_url }}
|
||||
org.opencontainers.image.source=${{ fromJson(steps.repo.outputs.result).clone_url }}
|
||||
org.opencontainers.image.created=${{ steps.prep.outputs.created }}
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
org.opencontainers.image.licenses=${{ fromJson(steps.repo.outputs.result).license.spdx_id }}
|
||||
cache-from: type=local,src=/tmp/.buildx-cache
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache,mode=max
|
||||
build-args: |
|
||||
BUILD_DATE=${{ steps.prep.outputs.build-date }}
|
||||
REVISION=${{ github.sha }}
|
||||
|
||||
- name: Inspect
|
||||
run: |
|
||||
|
|
|
@ -128,10 +128,18 @@ jobs:
|
|||
- name: Checkout
|
||||
uses: actions/checkout@v2.3.3
|
||||
|
||||
- name: Repo metadata
|
||||
id: repo
|
||||
uses: actions/github-script@v3.0.0
|
||||
with:
|
||||
script: |
|
||||
const repo = await github.repos.get(context.repo)
|
||||
return repo.data
|
||||
|
||||
- name: Prepare
|
||||
id: prep
|
||||
run: |
|
||||
echo ::set-output name=build-date::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
||||
echo ::set-output name=created::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1.0.1
|
||||
|
@ -193,12 +201,19 @@ jobs:
|
|||
${{ matrix.docker-image }}:${{ needs.release-semantic.outputs.release-version }}
|
||||
${{ matrix.docker-image }}:${{ needs.release-semantic.outputs.release-version-major }}.${{ needs.release-semantic.outputs.release-version-minor }}
|
||||
${{ matrix.docker-image }}:${{ needs.release-semantic.outputs.release-version-major }}
|
||||
labels: |
|
||||
org.opencontainers.image.title=${{ fromJson(steps.repo.outputs.result).name }}
|
||||
org.opencontainers.image.description=${{ fromJson(steps.repo.outputs.result).description }}
|
||||
org.opencontainers.image.url=${{ fromJson(steps.repo.outputs.result).html_url }}
|
||||
org.opencontainers.image.source=${{ fromJson(steps.repo.outputs.result).clone_url }}
|
||||
org.opencontainers.image.version=${{ needs.release-semantic.outputs.release-version }}
|
||||
org.opencontainers.image.created=${{ steps.prep.outputs.created }}
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
org.opencontainers.image.licenses=${{ fromJson(steps.repo.outputs.result).license.spdx_id }}
|
||||
cache-from: type=local,src=/tmp/.buildx-cache
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache,mode=max
|
||||
build-args: |
|
||||
VERSION=${{ needs.release-semantic.outputs.release-version }}
|
||||
BUILD_DATE=${{ steps.prep.outputs.build-date }}
|
||||
REVISION=${{ github.sha }}
|
||||
|
||||
- name: Update repo description
|
||||
uses: peter-evans/dockerhub-description@v2.4.0
|
||||
|
|
18
Dockerfile
18
Dockerfile
|
@ -9,7 +9,6 @@ RUN SKIP_BUILD=true npm ci
|
|||
COPY --chown=node:node . .
|
||||
|
||||
ARG VERSION
|
||||
ARG REVISION
|
||||
|
||||
RUN npm run build
|
||||
|
||||
|
@ -25,14 +24,6 @@ RUN npm prune --production
|
|||
|
||||
# production environment
|
||||
FROM node:14.13.1-alpine3.12 as production-stage
|
||||
LABEL org.opencontainers.image.title="SyncLounge"
|
||||
LABEL org.opencontainers.image.description="Enjoy Plex with your friends. In Sync. Together."
|
||||
LABEL org.opencontainers.image.url="https://synclounge.tv"
|
||||
LABEL org.opencontainers.image.source="https://github.com/synclounge/synclounge"
|
||||
LABEL org.opencontainers.image.vendor="SyncLounge"
|
||||
LABEL org.opencontainers.image.licenses="MIT"
|
||||
LABEL org.opencontainers.image.documentation="https://docs.synclounge.tv"
|
||||
|
||||
RUN mkdir /app && chown -R node:node /app
|
||||
WORKDIR /app
|
||||
COPY --chown=node:node server.js .
|
||||
|
@ -40,13 +31,4 @@ COPY --chown=node:node config config
|
|||
COPY --chown=node:node --from=dependency-stage /app/node_modules node_modules
|
||||
COPY --chown=node:node --from=build-stage /app/dist dist
|
||||
|
||||
ARG VERSION
|
||||
LABEL org.opencontainers.image.version=$VERSION
|
||||
|
||||
ARG REVISION
|
||||
LABEL org.opencontainers.image.revision=$REVISION
|
||||
|
||||
ARG BUILD_DATE
|
||||
LABEL org.opencontainers.image.created=$BUILD_DATE
|
||||
|
||||
ENTRYPOINT ["/app/server.js"]
|
|
@ -10,27 +10,9 @@ COPY --chown=node:node . .
|
|||
|
||||
ARG SERVERS
|
||||
ARG VERSION
|
||||
ARG REVISION
|
||||
|
||||
RUN npm run build
|
||||
|
||||
# production environment
|
||||
FROM nginx:1.19.3-alpine as production-stage
|
||||
LABEL org.opencontainers.image.title="SyncLounge Web"
|
||||
LABEL org.opencontainers.image.description="Enjoy Plex with your friends. In Sync. Together."
|
||||
LABEL org.opencontainers.image.url="https://synclounge.tv"
|
||||
LABEL org.opencontainers.image.source="https://github.com/synclounge/synclounge"
|
||||
LABEL org.opencontainers.image.vendor="SyncLounge"
|
||||
LABEL org.opencontainers.image.licenses="MIT"
|
||||
LABEL org.opencontainers.image.documentation="https://docs.synclounge.tv"
|
||||
|
||||
COPY --chown=nginx:nginx --from=build-stage /app/dist /usr/share/nginx/html
|
||||
|
||||
ARG VERSION
|
||||
LABEL org.opencontainers.image.version=$VERSION
|
||||
|
||||
ARG REVISION
|
||||
LABEL org.opencontainers.image.revision=$REVISION
|
||||
|
||||
ARG BUILD_DATE
|
||||
LABEL org.opencontainers.image.created=$BUILD_DATE
|
||||
COPY --chown=nginx:nginx --from=build-stage /app/dist /usr/share/nginx/html
|
|
@ -4332,11 +4332,21 @@
|
|||
"requires": {
|
||||
"anymatch": "~3.1.1",
|
||||
"braces": "~3.0.2",
|
||||
"fsevents": "~2.1.2",
|
||||
"glob-parent": "~5.1.0",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"fsevents": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
|
||||
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"chownr": {
|
||||
|
@ -6026,15 +6036,6 @@
|
|||
"integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==",
|
||||
"dev": true
|
||||
},
|
||||
"dotgitconfig": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/dotgitconfig/-/dotgitconfig-1.1.1.tgz",
|
||||
"integrity": "sha512-gkaAQMmhlE7N6NYtvckQ32f/xTX6Hv7RTtF9qKCYJEQgL/d6zJZk/D0eLFuuGPRCbpRj2PR/HcBLxtIh3MSB6Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ini": "^1.3.5"
|
||||
}
|
||||
},
|
||||
"duplexer": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
|
||||
|
@ -9158,15 +9159,6 @@
|
|||
"integrity": "sha512-eYboRV94Vco725nKMlpkn3nV2+96p9c3gKXRsYqAJSswSENvBhN7n5L+uDhY58xQa0UukWsDMTGELzmD8Q+wTA==",
|
||||
"dev": true
|
||||
},
|
||||
"last-commit-log": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/last-commit-log/-/last-commit-log-3.0.4.tgz",
|
||||
"integrity": "sha512-NwvGT6O3eiOIALwxa/i1YcVgQuLO7w/KheP3wORmB2JM9IaG47PbkSAn2BZMa8Z8hkPYblY+awD4lFjHFFsQ9g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"dotgitconfig": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"launch-editor": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.2.1.tgz",
|
||||
|
@ -15402,6 +15394,7 @@
|
|||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.0.0-beta.8.tgz",
|
||||
"integrity": "sha512-oouKUQWWHbSihqSD7mhymGPX1OQ4hedzAHyvm8RdyHh6m3oIvoRF+NM45i/bhNOlo8jCnuJhaSUf/6oDjv978g==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
|
@ -15413,6 +15406,7 @@
|
|||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
"eslint-plugin-vue": "^7.0.1",
|
||||
"fast-xml-parser": "^3.17.4",
|
||||
"husky": "^4.3.0",
|
||||
"last-commit-log": "^3.0.4",
|
||||
"lint-staged": "^10.4.0",
|
||||
"mux.js": "^5.6.4",
|
||||
"sass": "^1.27.0",
|
||||
|
@ -78,4 +77,4 @@
|
|||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
15
src/App.vue
15
src/App.vue
|
@ -159,7 +159,9 @@
|
|||
<script>
|
||||
import './assets/css/style.css';
|
||||
|
||||
import { mapActions, mapGetters, mapMutations } from 'vuex';
|
||||
import {
|
||||
mapActions, mapGetters, mapMutations, mapState,
|
||||
} from 'vuex';
|
||||
import redirection from '@/mixins/redirection';
|
||||
import clipboard from '@/mixins/clipboard';
|
||||
import linkWithRoom from '@/mixins/linkwithroom';
|
||||
|
@ -193,8 +195,6 @@ export default {
|
|||
'GET_SNACKBAR_OPEN',
|
||||
'GET_BACKGROUND',
|
||||
'GET_NAVIGATE_TO_PLAYER',
|
||||
'GET_REPOSITORY_URL',
|
||||
'GET_DISCORD_URL',
|
||||
'GET_NAVIGATE_HOME',
|
||||
]),
|
||||
|
||||
|
@ -220,17 +220,22 @@ export default {
|
|||
'GET_PASSWORD',
|
||||
]),
|
||||
|
||||
...mapState([
|
||||
'repositoryUrl',
|
||||
'discordUrl',
|
||||
]),
|
||||
|
||||
links() {
|
||||
return [
|
||||
{
|
||||
title: 'Github',
|
||||
href: this.GET_REPOSITORY_URL,
|
||||
href: this.repositoryUrl,
|
||||
target: '_blank',
|
||||
},
|
||||
{
|
||||
title: 'Discord',
|
||||
target: '_blank',
|
||||
href: this.GET_DISCORD_URL,
|
||||
href: this.discordUrl,
|
||||
},
|
||||
];
|
||||
},
|
||||
|
|
|
@ -64,12 +64,12 @@
|
|||
</v-list-item-icon>
|
||||
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>v{{ GET_VERSION }}</v-list-item-title>
|
||||
<v-list-item-title>v{{ version }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item
|
||||
:href="GET_DISCORD_URL"
|
||||
:href="discordUrl"
|
||||
target="_blank"
|
||||
>
|
||||
<v-list-item-icon>
|
||||
|
@ -82,7 +82,7 @@
|
|||
</v-list-item>
|
||||
|
||||
<v-list-item
|
||||
:href="GET_REPOSITORY_URL"
|
||||
:href="repositoryUrl"
|
||||
target="_blank"
|
||||
>
|
||||
<v-list-item-icon>
|
||||
|
@ -109,30 +109,11 @@
|
|||
</v-list-item>
|
||||
</DonateDialog>
|
||||
</v-list>
|
||||
|
||||
<template #append>
|
||||
<v-divider />
|
||||
<div
|
||||
class="text-center pa-2"
|
||||
style="opacity: 0.7; font-size: 12px;"
|
||||
>
|
||||
<div>
|
||||
Build <a
|
||||
class="text-decoration-none"
|
||||
:href="GET_COMMIT_URL"
|
||||
>
|
||||
#{{ GET_GIT_HASH.substring(0, 7) }}
|
||||
</a>
|
||||
</div>
|
||||
<div>Last updated {{ updatedAt }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</v-navigation-drawer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapMutations, mapState } from 'vuex';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
|
||||
export default {
|
||||
name: 'TheSidebarLeft',
|
||||
|
@ -143,47 +124,26 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['isLeftSidebarOpen']),
|
||||
...mapState([
|
||||
'isLeftSidebarOpen',
|
||||
'version',
|
||||
'repositoryUrl',
|
||||
'discordUrl',
|
||||
]),
|
||||
|
||||
...mapGetters([
|
||||
'GET_REPOSITORY_URL',
|
||||
'GET_VERSION',
|
||||
'GET_GIT_HASH',
|
||||
'GET_DISCORD_URL',
|
||||
'GET_RELEASE_URL',
|
||||
'GET_COMMIT_URL',
|
||||
]),
|
||||
|
||||
...mapGetters('plex', [
|
||||
'GET_PLEX_USER',
|
||||
]),
|
||||
|
||||
date() {
|
||||
return new Date(parseInt(process.env.VUE_APP_GIT_DATE, 10) * 1000);
|
||||
},
|
||||
|
||||
updatedAt() {
|
||||
return `${formatDistanceToNow(this.date)} ago`;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
...mapMutations([
|
||||
'SET_LEFT_SIDEBAR_OPEN',
|
||||
]),
|
||||
|
||||
getTimeFromMs(ms) {
|
||||
const hours = ms / (1000 * 60 * 60);
|
||||
const absoluteHours = Math.floor(hours);
|
||||
const h = absoluteHours > 9 ? absoluteHours : `0${absoluteHours}`;
|
||||
const minutes = (hours - absoluteHours) * 60;
|
||||
const absoluteMinutes = Math.floor(minutes);
|
||||
const m = absoluteMinutes > 9 ? absoluteMinutes : `0${absoluteMinutes}`;
|
||||
const seconds = (minutes - absoluteMinutes) * 60;
|
||||
const absoluteSeconds = Math.floor(seconds);
|
||||
const s = absoluteSeconds > 9 ? absoluteSeconds : `0${absoluteSeconds}`;
|
||||
return `${h}:${m}:${s}`;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,12 +1,5 @@
|
|||
export default {
|
||||
GET_VERSION: (state) => state.version,
|
||||
GET_GIT_HASH: (state) => state.gitHash,
|
||||
GET_REPOSITORY_URL: (state) => state.repositoryUrl,
|
||||
GET_DISCORD_URL: (state) => state.discordUrl,
|
||||
GET_RELEASE_URL: (state, getters) => `${getters.GET_REPOSITORY_URL}/releases/tag/v${
|
||||
getters.GET_VERSION}`,
|
||||
GET_COMMIT_URL: (state, getters) => `${getters.GET_REPOSITORY_URL}/commit/${
|
||||
getters.GET_GIT_HASH}`,
|
||||
GET_RELEASE_URL: (state) => `${state.repositoryUrl}/releases/tag/v${state.version}`,
|
||||
GET_BACKGROUND: (state) => state.background,
|
||||
GET_UP_NEXT_POST_PLAY_DATA: (state) => state.upNextPostPlayData,
|
||||
GET_CONFIG: (state) => state.configuration,
|
||||
|
|
|
@ -31,7 +31,7 @@ export default {
|
|||
|
||||
GET_PLEX_INITIAL_AUTH_PARAMS: (state, getters, rootState, rootGetters) => ({
|
||||
'X-Plex-Product': getters.GET_PLEX_PRODUCT_HEADER,
|
||||
'X-Plex-Version': rootGetters.GET_VERSION,
|
||||
'X-Plex-Version': rootState.version,
|
||||
'X-Plex-Client-Identifier': getters.GET_CLIENT_IDENTIFIER,
|
||||
'X-Plex-Platform': getters.GET_PLEX_PLATFORM_HEADER,
|
||||
'X-Plex-Platform-Version': rootGetters.GET_BROWSER.version,
|
||||
|
@ -58,7 +58,7 @@ export default {
|
|||
GET_PLEX_AUTH_URL: (state, getters, rootState, rootGetters) => (code) => {
|
||||
const urlParams = {
|
||||
'context[device][product]': getters.GET_PLEX_PRODUCT_HEADER,
|
||||
'context[device][version]': rootGetters.GET_VERSION,
|
||||
'context[device][version]': rootState.version,
|
||||
'context[device][platform]': getters.GET_PLEX_PLATFORM_HEADER,
|
||||
'context[device][platformVersion]': rootGetters.GET_BROWSER.version,
|
||||
'context[device][device]': getters.GET_PLEX_DEVICE_DEVICE_HEADER,
|
||||
|
|
|
@ -2,7 +2,6 @@ import { detect } from 'detect-browser';
|
|||
|
||||
const state = () => ({
|
||||
version: process.env.VUE_APP_VERSION,
|
||||
gitHash: process.env.VUE_APP_GIT_HASH,
|
||||
repositoryUrl: 'https://github.com/synclounge/synclounge',
|
||||
discordUrl: 'https://discord.gg/fKQB3yt',
|
||||
|
||||
|
|
|
@ -61,7 +61,6 @@ export default {
|
|||
computed: {
|
||||
...mapGetters([
|
||||
'GET_CONFIG',
|
||||
'GET_REPOSITORY_URL',
|
||||
]),
|
||||
|
||||
...mapGetters('plex', [
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
const path = require('path');
|
||||
const LCL = require('last-commit-log');
|
||||
|
||||
const lcl = new LCL();
|
||||
|
||||
const config = require('./config');
|
||||
|
||||
|
@ -14,17 +11,6 @@ const pkgVersion = require('./package.json').version;
|
|||
|
||||
process.env.VUE_APP_VERSION = process.env.VERSION || pkgVersion;
|
||||
|
||||
try {
|
||||
const lastCommit = lcl.getLastCommitSync();
|
||||
process.env.VUE_APP_GIT_HASH = lastCommit.hash;
|
||||
process.env.VUE_APP_GIT_DATE = lastCommit.committer.date;
|
||||
} catch (e) {
|
||||
// Sometimes on CI stuff they build with .git being present
|
||||
// TODO: find better way to do this
|
||||
process.env.VUE_APP_GIT_DATE = Math.floor(Date.now() / 1000);
|
||||
process.env.VUE_APP_GIT_HASH = process.env.REVISION;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
// Relative publicPath to support subfolders
|
||||
publicPath: '',
|
||||
|
|
Loading…
Reference in New Issue