Skip to content

Commit 53bdc8e

Browse files
sampsonjchrlaneywrightj3
authored
v2.13.0 (NEONScience#83)
* add ability to override API host validation * add platform specification to docker builds * update links, merge latest * updated paths * add docker bake * regen lib * Add workflow for building and push Docker image * Set build to push image * Set build trigger to main * prepare v2.13.0, regen lib, web server version update --------- Co-authored-by: Christine Laney <[email protected]> Co-authored-by: Justin Wright <[email protected]>
1 parent 3ced9e6 commit 53bdc8e

File tree

23 files changed

+237
-66
lines changed

23 files changed

+237
-66
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: Docker Publish
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
tags: [ 'v*' ]
7+
env:
8+
GCP_ARTIFACT_HOST: ${{ vars.SHARED_WIF_LOCATON }}-docker.pkg.dev
9+
GCP_REGISTRY: ${{ vars.SHARED_WIF_LOCATON }}-docker.pkg.dev/${{ vars.SHARED_WIF_PROJECT }}/${{ vars.SHARED_WIF_REPO }}
10+
GCP_BEI_REGISTRY: ${{ vars.SHARED_WIF_LOCATON }}-docker.pkg.dev/${{ vars.SHARED_WIF_PROJECT }}/bei
11+
IMAGE_NAME: portal-react-core-components
12+
13+
jobs:
14+
docker-publish:
15+
runs-on: ubuntu-latest
16+
permissions:
17+
id-token: write
18+
contents: read
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@v4
22+
23+
- name: Google Auth
24+
id: 'auth'
25+
uses: 'google-github-actions/auth@v2'
26+
with:
27+
workload_identity_provider: "${{ vars.SHARED_WIF_PROVIDER }}"
28+
service_account: "${{ vars.SHARED_WIF_SERVICE_ACCOUNT }}"
29+
token_format: 'access_token'
30+
31+
- name: Docker Login
32+
uses: 'docker/login-action@v3'
33+
with:
34+
registry: ${{ env.GCP_ARTIFACT_HOST }}
35+
username: 'oauth2accesstoken'
36+
password: ${{ steps.auth.outputs.access_token }}
37+
38+
- name: Docker Buildx Setup
39+
uses: docker/setup-buildx-action@v3
40+
41+
- name: Docker Metadata
42+
id: meta
43+
uses: docker/metadata-action@v5
44+
with:
45+
images: ${{ env.GCP_REGISTRY }}/${{ env.IMAGE_NAME }}
46+
tags: |
47+
type=raw,value=v-latest
48+
type=ref,event=tag
49+
type=sha
50+
flavor: |
51+
latest=false
52+
53+
- name: Docker Build
54+
uses: docker/bake-action@v6
55+
env:
56+
REPO: ${{ env.GCP_BEI_REGISTRY }}
57+
with:
58+
source: .
59+
files: |
60+
./docker-bake.hcl
61+
${{ steps.meta.outputs.bake-file }}
62+
push: true

bake.Dockerfile

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#-------------------------------------------------------------------------------
2+
# Builder container for reproducible build environment
3+
4+
FROM portal-react-apps/node:current AS builder
5+
6+
ENV GENERATE_SOURCEMAP=false
7+
ENV NODE_OPTIONS=--max_old_space_size=4096
8+
9+
WORKDIR /app
10+
COPY . ./build-temp/portal-core-components
11+
12+
WORKDIR /app/build-temp/portal-core-components
13+
RUN npm ci
14+
RUN npm run build
15+
RUN mv ./build /app/
16+
RUN rm -rf /app/build-temp
17+
18+
#-------------------------------------------------------------------------------
19+
# Build production container with only necessary artifacts
20+
21+
FROM portal-web-server-builder:current AS server-builder-parent
22+
FROM alpine:3.20
23+
24+
EXPOSE 3006
25+
26+
WORKDIR /opt/go/app
27+
28+
COPY --from=builder /app .
29+
COPY --from=server-builder-parent /usr/src/app/go-web-server .
30+
31+
# Set app wide env variables
32+
ENV PORTAL_PORT=3006
33+
ENV PORTAL_CLIENT_ROUTE="/core-components"
34+
35+
RUN addgroup --gid 1301 portal-react \
36+
&& adduser -u 444 -D -G portal-react portal-react \
37+
&& chown -R portal-react:portal-react /opt/go/app \
38+
&& cd /home/portal-react \
39+
&& mkdir -p config/portal/apps
40+
41+
USER portal-react
42+
43+
ENTRYPOINT exec ./server \
44+
-port=$PORTAL_PORT \
45+
-app-client-route=$PORTAL_CLIENT_ROUTE \
46+
-app-api-host=$REACT_APP_NEON_API_HOST \
47+
-app-web-host=$REACT_APP_NEON_WEB_HOST \
48+
-app-api-token=$REACT_APP_NEON_SERVICE_API_TOKEN \
49+
-app-auth-silent-type=$REACT_APP_NEON_AUTH_SILENT_TYPE \
50+
-app-cookie-domain=$PORTAL_SERVER_APP_COOKIE_DOMAIN

docker-bake.hcl

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
variable "NODE_VERSION" {
2+
default = "22.5"
3+
}
4+
5+
# Populated from GitHub Action
6+
variable "REPO" {
7+
default = ""
8+
}
9+
10+
group "default" {
11+
targets = [
12+
"portal-core-components",
13+
]
14+
}
15+
16+
# Populated from GitHub Action
17+
target "docker-metadata-action" {
18+
tags = []
19+
}
20+
21+
target "bootstrap" {
22+
platforms = [ "linux/amd64" ]
23+
no-cache = true
24+
}
25+
26+
target "portal-core-components" {
27+
inherits = ["bootstrap", "docker-metadata-action"]
28+
tags = [for tag in target.docker-metadata-action.tags : tag]
29+
dockerfile = "bake.Dockerfile"
30+
contexts = {
31+
"portal-web-server-builder:current" = "docker-image://${REPO}/portal-web-server-builder:v2.0.0"
32+
"portal-react-apps/node:current" = "docker-image://node:${NODE_VERSION}-alpine"
33+
}
34+
}

lib/components/ExternalHost/ExternalHost.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ const externalHosts = {
281281
id: 'BOLD',
282282
name: 'BOLD',
283283
projectTitle: 'BOLD (Barcode of Life Datasystem)',
284-
url: 'http://www.barcodinglife.com/',
284+
url: 'https://boldsystems.org/',
285285
hostType: HOST_TYPES.ADDITIONAL_DATA,
286286
linkType: LINK_TYPES.BY_PRODUCT,
287287
hostDataVariety: 'Raw sequence data',
@@ -292,7 +292,7 @@ const externalHosts = {
292292
}
293293
return externalProducts[productCode].searches.map(search => ({
294294
key: search.query,
295-
node: renderExternalHostLink("http://www.boldsystems.org/index.php/Public_SearchTerms?query=".concat(search.query), search.title, 'BOLD', productCode)
295+
node: renderExternalHostLink("https://portal.boldsystems.org/recordset/".concat(search.query), search.title, 'BOLD', productCode)
296296
}));
297297
}
298298
},

lib/components/NeonEnvironment/NeonEnvironment.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export declare const requiredEnvironmentVars: string[];
1010
export declare const optionalEnvironmentVars: string[];
1111
export interface NeonServerData {
1212
NeonPublicAPIHost: Undef<string>;
13+
NeonPublicAPIHostAllowInternal: Undef<boolean>;
1314
NeonWebHost: Undef<string>;
1415
NeonPublicAPITokenHeader: Undef<string>;
1516
NeonPublicAPIToken: Undef<string>;

lib/components/NeonEnvironment/NeonEnvironment.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,13 @@ const NeonEnvironment = {
150150
getNeonServerDataApiHost: () => {
151151
const serverData = NeonEnvironment.getNeonServerData();
152152
if (serverData && typeof serverData.NeonPublicAPIHost === 'string') {
153+
const allowInternal = typeof serverData.NeonPublicAPIHostAllowInternal === 'boolean' ? serverData.NeonPublicAPIHostAllowInternal : false;
153154
const apiHost = serverData.NeonPublicAPIHost;
154155
try {
155156
const {
156157
hostname: apiHostname
157158
} = new URL(apiHost);
158-
if (NeonEnvironment.isApiHostValid(apiHostname)) {
159+
if (NeonEnvironment.isApiHostValid(apiHostname) || allowInternal) {
159160
return apiHost;
160161
}
161162
} catch (e) {

lib/components/SiteMap/SiteMapFeature.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,7 +1436,7 @@ const SiteMapFeature = props => {
14361436
}
14371437
if (state.map.zoomedIcons[featureKey] !== null) {
14381438
const baseIcon = state.map.zoomedIcons[featureKey];
1439-
const selection = isSelectable && isSelected ? _SiteMapUtils.SELECTION_STATUS.SELECTED : _SiteMapUtils.SELECTION_STATUS.UNSELECTED;
1439+
const selection = isSelectable && isSelected && (0, _typeUtil.exists)(baseIcon) && (0, _typeUtil.exists)(baseIcon[_SiteMapUtils.SELECTION_STATUS.SELECTED]) ? _SiteMapUtils.SELECTION_STATUS.SELECTED : _SiteMapUtils.SELECTION_STATUS.UNSELECTED;
14401440
const initialHighlight = isHighlighted ? _SiteMapUtils.HIGHLIGHT_STATUS.HIGHLIGHT : _SiteMapUtils.HIGHLIGHT_STATUS.NONE;
14411441
if (baseIcon && baseIcon[selection]) {
14421442
icon = baseIcon[selection][initialHighlight];
@@ -1489,12 +1489,14 @@ const SiteMapFeature = props => {
14891489
};
14901490
}
14911491
}
1492-
marker = /*#__PURE__*/_react.default.createElement(_reactLeaflet.Marker, _extends({
1493-
key: "".concat(key, "-marker"),
1494-
position: position,
1495-
title: key,
1496-
icon: icon
1497-
}, interaction), renderedPopup);
1492+
if ((0, _typeUtil.exists)(icon)) {
1493+
marker = /*#__PURE__*/_react.default.createElement(_reactLeaflet.Marker, _extends({
1494+
key: "".concat(key, "-marker"),
1495+
position: position,
1496+
title: key,
1497+
icon: icon
1498+
}, interaction), renderedPopup);
1499+
}
14981500
}
14991501
switch (featureShape) {
15001502
case 'Marker':

lib/components/SiteMap/SiteMapUtils.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ var _cloneDeep = _interopRequireDefault(require("lodash/cloneDeep"));
99
var _leaflet = _interopRequireDefault(require("leaflet"));
1010
var _Theme = require("../Theme/Theme");
1111
var _RouteService = _interopRequireDefault(require("../../service/RouteService"));
12+
var _typeUtil = require("../../util/typeUtil");
1213
var _iconPlaceholder = _interopRequireDefault(require("./svg/icon-placeholder.svg"));
1314
var _iconShapeCircleShadow = _interopRequireDefault(require("./svg/icon-shape-circle-shadow.svg"));
1415
var _iconShapeCircleSelect = _interopRequireDefault(require("./svg/icon-shape-circle-select.svg"));
@@ -1789,13 +1790,16 @@ const getZoomedIcon = function () {
17891790
} = shadow[highlight] || {};
17901791
// Adjust icon, size, and anchor if selected (and a different "selected" icon is available)
17911792
if (featureHasIcon && selection === SELECTION_STATUS.SELECTED && feature.iconSelectedSvg) {
1792-
iconUrl = feature.iconSelectedSvg;
1793+
iconUrl = (0, _typeUtil.exists)(feature.iconSelectedSvg) ? feature.iconSelectedSvg : _iconPlaceholder.default;
17931794
iconSize = iconSize.map(d => d + SELECTED_ICON_OFFSET);
17941795
iconAnchor = iconAnchor.map(d => d + SELECTED_ICON_OFFSET / 2);
17951796
shadowSize = shadowUrl ? shadowSize.map(d => d + SELECTED_ICON_OFFSET) : null;
17961797
shadowAnchor = shadowUrl ? shadowAnchor.map(d => d + SELECTED_ICON_OFFSET / 2) : null;
17971798
popupAnchor[1] -= SELECTED_ICON_OFFSET / 2;
17981799
}
1800+
if (!(0, _typeUtil.exists)(iconUrl)) {
1801+
iconUrl = _iconPlaceholder.default;
1802+
}
17991803
// Determine Icon Scale
18001804
// Normalize the scale to a range of at least 0.2 to 0.5 (but as big as 0.2 to 1) based on
18011805
// current zoom and feature zoom bounds, then multiply by any feature icon scale

lib/remoteAssets/drupal-header.html.d.ts

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

lib/remoteAssets/drupal-header.html.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)