メインコンテンツまでスキップ

2025年、AI業界の6つの転換(Karpathy氏2025年まとめ)

· 約16分
Mikyan
白い柴犬

2025年、AI業界は驚くべきスピードで進化している。2024年末までAIは「質問に答えるだけの文章生成ツール」に過ぎないと思われがちだったが、いまや各業界で実際のビジネス価値を生み出す存在へと変わってきた。 なぜたった一年でここまで進化したのか。振り返ってみると、カーパシー氏は6つの転換点を挙げている。この6つの転換点は、今後10年のLLMの進化にも影響しうるほど重要と思うので、ここで簡単に紹介したい。

もともとLLMの訓練パイプラインは、事前学習 → SFT → RLHF の3段階が定番でした。ところが2025年にはRLVRが一躍“第4の主要ステージ”として存在感を増しました。

LLMの発展をざっくり振り返ると、2020年ごろの主流は事前学習(Pretraining)です。大量のテキストを学習させ、言語の基礎能力を作ります。 その後、2022年ごろからSFT(教師あり微調整)とRLHFが広く使われるようになりました。

SFT(Supervised Fine-Tuning)は一言でいうと、**「お手本を見せて、指示に従う練習をさせる段階」**です。 事前学習を終えたモデルに対して、人間が用意した「質問 → 理想的な回答」のペアを大量に学習させ、出力の品質を引き上げます。

一方RLHF(Reinforcement Learning from Human Feedback)は、人間がLLMの出力を評価し、その人間の選好に基づく報酬でモデルを最適化することで、より好ましい回答を返せるように調整する手法です。

ただし、SFTもRLHFも人間がモデルに「推論そのもの(途中の思考プロセス)」を直接教えるのは難しく、推論力を狙った形で育てにくいという課題があります。 多くの場合、人間が与えるフィードバックは最終回答の良し悪しに寄りがちで、途中の考え方まで十分に教師信号として与えられないからです。

そもそも人間にとっても、「最善の推論ルート」を明確に定義するのは簡単ではありません。たとえば数学の問題を解くとき、頭の中では省略している判断や暗黙の手順が多く、それを文章として整理してLLMに伝えるのは難しいのです。

そこで登場したのがRLVR(Reinforcement Learning from Verifiable Rewards)です。RLVRを一言でいうと、人間が評価する代わりに「自動で正誤を検証できる採点器(verifier)」を用意し、その合否を報酬信号として学習させる手法です。

たとえば「数学なら答えが一致しているか」「コードならテストに通るか」のように、外部の検証器で白黒がつくタスクを作れます。

出力を採点器にかけて、合格ならスコア(報酬)= 1

不合格ならスコア(報酬)= 0(または低スコア)

この“自動採点ループ”を回しながら、モデルに大量の試行錯誤をさせます。

以前は「人間が先生」でしたが、RLVRでは「自動採点できる世界」を先に作り、モデルに大量の練習問題を解かせます。結果としてモデルは、正解に到達するための手順(推論の組み立て方)を、外部の正誤判定に合わせて内側で洗練していきます。

さらにRLVRは、SFTのように「短い微調整で終わる」だけではなく、報酬に向けた最適化を比較的長く回せるのが特徴です。実際に2025年は、パラメータを増やすよりも、RLVRを長く回す方向に計算資源が寄っていった――という見方もあります。

またRLVRが広がると、もう1つ重要な軸が出てきます。それが**「テスト時にどれだけ考えさせるか」**です。推論(考える過程)により多くの計算を使わせるほど、正解率が上がるケースがあります。

そのためアプリ側でも、ざっくり言えば、

Thinking(短い)=速い・安いが、難問に弱い

Thinking(長い)=遅い・高いが、難問に強い

のように、性能を“考える時間”で調整しやすくなりました。

RLVR方法に基づいて、OpenAIは2024年末で推論モデル(oシリーズ)を提供し始めます。o1は初めての推論モデルで、o3は高い推論能力を持っているモデルで注目されました。

転換2、我々は動物を育てているのではなく、幽霊を召喚している

人間(動物)の脳は「生存のため」に最適化されてきました。 しかしLLMは違います。LLMが最適化される圧力は、例えば次のようなものです:

  • 人類のテキストを模倣する(次の単語を当て続ける)

  • 数学やコードで報酬を取る

  • 人間の評価(ランキング)を取る

その結果として現れる知能の形は、人間や動物と同じになりません。

2025年のLLMは、**「ある分野では天才なのに、別の分野では驚くほど脆い」という特徴が目立ちます。 能力が滑らかに均一ではなく、領域ごとに尖ったり凹んだりする――この状態を、ここでは「ギザギザ」**と呼びます。

この見方をすると、「ベンチマークで勝っているのに、なぜAGIとは言い切れないのか?」という違和感も説明しやすくなります。

ベンチマークは多くの場合、正解が定義できる=検証可能です。 するとRLVRや合成データによって、**「ベンチマーク周辺だけ能力を盛る」**ことが相対的にやりやすくなります。

Karpathyは、こうした“ベンチマーク対策”が高度化し、「テストで勝つ技術」そのものが一つの芸になっている、という冷めた見方も示しています。

転換3、CursorとLLMアプリの新しい層

2025年は「Cursor for X」という言い方が広がり、Cursorの台頭が**“LLMアプリ”という新しいレイヤー**をはっきり可視化しました。

ここで重要なのは、LLMアプリが単に「チャット画面を用意するだけ」ではなく、特定の業務(縦の領域)に向けてLLMを束ね、使える形に組み立てるところに価値がある点です。

Karpathyは、LLMアプリ(Cursorのようなプロダクト)がやっていることを大きく4つに整理しています。

  • コンテキスト設計(context engineering):何を、どう渡すかを設計する

  • 複数回呼び出しのオーケストレーション:裏で複数回LLMを回し、複雑な処理フロー(DAG)として組む(性能とコストのバランスも取る)

  • GUI(Human-in-the-loop):人間が介入・確認しやすいUIを用意する

  • 自律性スライダー(autonomy slider):どこまでAIに任せるかをユーザーが調整できるようにする

つまり「LLMを1回呼んで終わり」ではなく、業務に合わせて一連の流れとして設計・統合すること自体が価値になってきた、という話です。

Karpathyは、2025年に議論された論点として「この新しいアプリ層がどれだけ“厚く”なるか」を挙げています。

その上で、LLMラボは“汎用的に優秀な大学生”を育てる方向に進む一方、アプリ側はそれらを特定領域で稼働する“現場のプロ”に仕立てる方向に進むのではないか、と見ています。

その鍵になるのが、アプリ側が提供できる次の要素です。

  • 企業の私有データ
  • センサーや操作(アクチュエータ)=現実世界への入出力
  • フィードバックループ(使われながら改善される循環)

変化④:Claude Code「PCに住むAI」

4つ目はAnthropicの Claude Code(CC) です。Karpathyはこれを、**LLM Agentの“最初の説得力ある例”**として挙げています。チャットで助言するだけでなく、ツール利用と推論を行き来しながら、まとまった作業を最後までやり切れる感覚がある、という評価です。

CCの面白さは「クラウドで動くAI」ではなく、自分のPC上(localhost)で動くところにあります。開発者の環境やファイル、設定、履歴(そしてシークレット)と密接につながることで、AIは単なるWebサービスではなく、**PCに“住む存在”**に近づいていく――という見立てです。

この文脈でKarpathyは、OpenAIが一時期「クラウドのコンテナ上で動くエージェント(ChatGPT側のオーケストレーション)」に寄りすぎた点に、やや批判的です。能力がまだギザギザな過渡期だからこそ、現実的には開発者と並走しながらローカル環境で地に足をつけて動くほうが合理的だ、という視点になります。

さらにCCが ミニマルなCLI として提供されたことも象徴的です。AIは「Webサイトに行って使うもの」から、PCの中に常駐して必要なときに呼び出せる――いわば**“PCに住む小さな精霊”**のような存在へ。ここに新しい対話パラダイムが生まれた、というわけです。

変化⑤:Vibe coding(雰囲気でコーディング)

5つ目は、Karpathy自身が広めた言葉 「Vibe coding」 です。

2025年は、英語(自然言語)で指示するだけで、実用的なプログラムを作れるだけの能力閾値をLLMが越えた年でした。結果として、「コードを理解して手で書く」ことの比重が下がり、**“コードの存在を忘れて作る”**感覚が現実的になってきます。

このスタイルが広がると、開発はこう変わります。

  • とりあえず作る

  • すぐ捨てる

  • 目的のためだけに、短命なコードを書く(使い捨てのミニアプリ)

Karpathyは実際に、デモや小さな道具を次々に作ったり、**バグを1つ潰すためだけの“使い捨てアプリ”**を作ったりするようになった、と述べています。コードが「安く」「柔らかく」「捨てやすい」ものになった、というわけです。

これは一般の人にとっては“プログラミングの民主化”であり、プロにとっても「今までコスト的に作れなかったソフトが作れる」状態を生みます。そして仕事の定義や職能にも影響していく、と見ています。

変化⑥:Nano banana と LLMのGUI化

最後が、Google Geminiの “Nano banana” です。Karpathyはこれを、2025年の中でも特に印象的で“パラダイムシフト級”の例として挙げています。

ここで言いたいのは、単なる画像生成の性能向上だけではありません。

彼は「いまのLLMとの対話(チャット)」を、1980年代のコンソール操作になぞらえます。テキストはコンピュータには都合が良い一方で、人間にとっては読むのも書くのも遅く、疲れる。だからコンピュータ史ではGUIが生まれた――同じことがLLMでも起きる、という見立てです。

つまりLLMは、テキストだけでなく人間が得意な形式で返す方向へ進むはずだ、と。

  • 画像

  • インフォグラフィック

  • スライド

  • ホワイトボード

  • アニメーション/動画

  • Webアプリ

そしてnano bananaは、その“LLMのGUI化”の早い兆しだと言います。重要なのは、画像生成だけではなく、テキスト生成・画像生成・世界知識がモデルの中で一体になって働く点にある――という評価です。

swe-bench-sonnet

· 約1分

SWE-bench is an AI evaluation benchmark that assesses a model's ability to complete real-world software engineering tasks.

Each solution is graded against the real unit tests from the pull request that closed the original GitHub issue

https://www.swebench.com/

読書:building-effective-agents

· 約3分
Mikyan
白い柴犬

Agentsとは、LLMを使って動的にプロセスを決めて、ツールを使って、タスクを完成するシステムです。

シンプルのはベスト。必要の時だけAgentを作成。

Agentic systems often trade latency and cost for better task performance, and you should consider when this tradeoff makes sense.

workflows offer predictability and consistency for well-defined tasks, whereas agents are the better option when flexibility and model-driven decision-making are needed at scale.

  • LangGraph from LangChain;
  • Amazon Bedrock's AI Agent framework;
  • Rivet, a drag and drop GUI LLM workflow builder; and
  • Vellum, another GUI tool for building and testing complex workflows.

Building blocks

The augmented LLM: LLM enhanced with augmentations such as retrieval, tools, and memory

https://www.anthropic.com/_next/image?url=https%3A%2F%2Fwww-cdn.anthropic.com%2Fimages%2F4zrzovbb%2Fwebsite%2Fd3083d3f40bb2b6f477901cc9a240738d3dd1371-2401x1000.png&w=3840&q=75

There are many ways to implement the augmentations, MCP allows developers to integrate with a growing ecosystem of third party tools with a simple client implementation.

Workflow: Prompt chaining.

Decomposes a task into a sequence of steps, where each LLM call processes the output of the previous one

Workflow is ideal for situations where the task can be easily and cleanly decomposed into fixed subtasks. The main goal is to trade off latency for higher accuracy, by making each LLM call an easier task.

Workflow:

Routing: classifies an input and directs it to a specialized followup task, for separation of concerns, and build more specialized prompts.

Parallelization: work simultaneously on a task and have their outputs aggregated programmatically.

  • Sectioning: breaking a task into independent subtasks run in parallel
  • Voting: running the same task multiple times to get diverse outputs

Orchestrator-workers: a central LLM dynamically breaks down tasks, delegates them to worker LLMs, and synthesizes their results.

Well suited for complex tasks, where you can't predict the subtasks needed. subtasks aren't pre-defined, but determined by the orchestrator based on the specific input.

Evaluator-optimizer: LLM call generates a response while another provides evaluation and feedback in a loop.

effective when we have clear evaluation criteria, and when iterative refinement provides measurable value.

Agents

Agents begin their work with either a command from, or interactive discussion with, the human user. Once the task is clear, agents plan and operate independently, potentially returning to the human for further information or judgement.

During execution, it's crucial for the agents to gain ground truth, from the environment at each step, to assess its progress. Agents can then pause for human feedback at checkpoints or when encountering blockers.

Implementation is often straightforward. They are typically just LLMs using tools based on environmental feedback in a loop. It is therefore curtial to design toolsets and their documentation clearly and thoughtfully.

when to use agents: used for open-ended problems where it's difficult or impossible to predict the required number of steps, and where you can't hardcode a fixed path.

It's about building the right system for your needs. Start with simple prompts, optimize them with comprehensive evaluation, and add multi-step agentic systems only when simpler solutions fall short.

Build Agent Cookbook

References

Source Blog: https://www.anthropic.com/engineering/building-effective-agents

https://github.com/anthropics/anthropic-cookbook/tree/main/patterns/agents

Agent uses

https://www.anthropic.com/engineering/swe-bench-sonnet

https://github.com/anthropics/anthropic-quickstarts/tree/main/computer-use-demo

読書:Context RetrivalによるRAGの精度向上

· 約2分
Mikyan
白い柴犬
  • LLMがプライベートデータを使って問題を解決する場合は、RAGで関連知識を検索し、コンテキストとして背景知識に取り込むのが基本
  • RAGが抱える課題の一つは、チャンク分割によって知識が分断され、活用できなくなることである
  • Context Retrievalによってチャンクごとにコンテキストを追加し、背景情報を補足することで、知識を補完できる
  • さらに、検索結果のリランキングによって検索精度を向上させ、より適切な知識を抽出し、質の高いコンテキストを生成できる

RAGによる知識補足

LLMをビジネス問題を取り込むときに、ビジネス関連の背景知識不足は一つ大きな制約です。オーブンデータで訓練したLLMは、特化したビジネス知識(特には特定会社のプライベートデータ)への勉強不足、 関連問題を思った通りの解決はできない。

LangChain

· 約6分
Mikyan
白い柴犬

LangChainは、LLMアプリケーションを手軽に開発できるフレームワークです。

LangChainを使うことで、以下の4つのメリットがあります:

  • 構成性(Composability):シンプルなコンポーネントを組み合わせて、複雑なAIワークフローを構築できる
  • 抽象化(Abstraction):異なるLLMやベクターストアを共通のインターフェースで扱える
  • メモリ管理(Memory):対話の文脈(コンテキスト)を保持・管理できる
  • ツール連携(Tools):LLMを外部データや機能と接続できる

基本構成

モデル(Model):LLMを共通のインターフェースで扱うためのラッパー

import { ChatOpenAI } from "@langchain/openai";
import { ChatAnthropic } from "@langchain/anthropic";

// All models share the same interface
const openAIModel = new ChatOpenAI({
modelName: "gpt-4",
temperature: 0.7,
});

const anthropicModel = new ChatAnthropic({
modelName: "claude-3-sonnet",
temperature: 0.7,
});

// Same method works for both
const response = await openAIModel.invoke("Hello, how are you?");

メッセージ(Messages):LLMとの通信フォーマット

LangChainでは、LLMとのやり取りにメッセージベースのシステムを採用しています。

これは、GPT-4やClaudeのような最新のチャットモデルが、単一のプロンプトではなく「会話形式」で動作するように設計・訓練されているためです。

LangChainのメッセージシステムは、こうしたモデルの学習形式やAPIの構造に合わせたものです。

各メッセージは、会話内の1ターンを表す構造化オブジェクトで、以下の要素を持ちます:

  • ロール(role):誰が話しているか(例:ユーザー、システム、アシスタント)
  • 内容(content):メッセージの本文
  • メタデータ(metadata):任意の補足情報(省略可能)
import { HumanMessage, SystemMessage, AIMessage } from "@langchain/core/messages";

const messages = [
new SystemMessage("You are a helpful assistant"),
new HumanMessage("What's the weather like?"),
new AIMessage("I don't have access to real-time weather data..."),
];

プロンプト(Prompt):LangChainにおいて、メッセージを生成するためのテンプレート、いわばメッセージの工場です。

import { ChatPromptTemplate } from "@langchain/core/prompts";

const prompt = ChatPromptTemplate.fromTemplate(
"You are a {role}. Answer this question: {question}"
);

const formattedPrompt = await prompt.format({
role: "scientist",
question: "What is photosynthesis?"
});
const chatPrompt = ChatPromptTemplate.fromMessages([
["system", "You are {role}. Always be {personality}."],
["human", "{query}"]
]);

// Generates multiple messages
const messages = await chatPrompt.formatMessages({
role: "a chef",
personality: "enthusiastic and encouraging",
query: "How do I make pasta?"
});
// Result:
// [
// SystemMessage { content: "You are a chef. Always be enthusiastic and encouraging." },
// HumanMessage { content: "How do I make pasta?" }
// ]

チェーン(Chain):コンポーネント同士を直列につなげる構成パターン

Output Parsers - Structure Results

import { z } from "zod";
import { StructuredOutputParser } from "langchain/output_parsers";

const parser = StructuredOutputParser.fromZodSchema(
z.object({
name: z.string(),
age: z.number(),
interests: z.array(z.string())
})
);

// Parser generates format instructions for the LLM
const formatInstructions = parser.getFormatInstructions();

Runnable: the foundational abstraction in LangChain, represents any component that can process input and produce output.

invoke() - Single Request, Complete Reponse

processes one input and returns the complete output after processing is done

  • you need the full response before proceeding
  • simple request-repsonse patterns
  • when you don't need real-time feedback

stream() - Single Request, Streaming Response

Use when:

  • Real-time UI updates
  • Large responses that take time
  • Better user experience with immediate feedback
  • Processing data as it arrives
const model = new ChatOpenAI();

// Streaming response - chunks arrive as generated
const stream = await model.stream("Write a long story about space");

for await (const chunk of stream) {
process.stdout.write(chunk.content); // Print each chunk as it arrives
}

batch() - multiple Requests, parallel processing

  • processing multiple items efficiently
  • bulk operations
  • when you have rate limits but want parallelism
  • analyzing multiple documents simultaneously

Runnables can be chained using .pipe():

const chain = prompt
.pipe(model)
.pipe(outputParser)
.pipe(customProcessor);

// All three methods work on chains
await chain.invoke(input);
await chain.stream(input);
await chain.batch(inputs);

Everything in LangChain implements the Runnable interface

interface Runnable {
invoke(input: any): Promise<any>;
stream(input: any): AsyncGenerator<any>;
batch(inputs: any[]): Promise<any[]>;
}

Work together

import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { StringOutputParser } from "@langchain/core/output_parsers";

// 1. Create components
const model = new ChatOpenAI({ temperature: 0 });
const prompt = ChatPromptTemplate.fromTemplate(
"Tell me a joke about {topic}"
);
const outputParser = new StringOutputParser();

// 2. Chain them together
const chain = prompt.pipe(model).pipe(outputParser);

// 3. Run the chain
const joke = await chain.invoke({ topic: "programming" });
// Input → Prompt → Model → Parser → Output

Memory system maintains conversation context:

Memory in LangChain is both the messages, and additional context / summaries.

Memory = Conversation History + State Management:

Memory in LangChain is a system that:

  • Stores the conversation history (messages)
  • Manages how that history is used
  • Can transform/summarize the history
  • Decides what to remember and what to forget

Types of Memory:

  • BufferMemory: Stores Everything
  • BufferWindowMemory - Limited History
  • ConversationSummaryMemory - Compressed History
  • ConversationSummaryBufferMemory - Hybrid Approach
import { BufferMemory } from "langchain/memory";
import { ConversationChain } from "langchain/chains";

const memory = new BufferMemory();
const chain = new ConversationChain({
llm: model,
memory: memory,
});

// First interaction
await chain.call({ input: "My name is Alice" });
// Second interaction remembers the first
await chain.call({ input: "What's my name?" }); // Knows it's Alice

Document Processing Pipeline: For RAG (Retrieval Augmented Generation):

const loader = new TextLoader("./document.txt");
const docs = await loader.load();

// 2. Split into chunks
const splitter = new RecursiveCharacterTextSplitter({
chunkSize: 1000,
chunkOverlap: 200,
});
const chunks = await splitter.splitDocuments(docs);

// 3. Create embeddings and store
const embeddings = new OpenAIEmbeddings();
const vectorStore = await MemoryVectorStore.fromDocuments(
chunks,
embeddings
);

// 4. Create retrieval chain
const retriever = vectorStore.asRetriever();
const chain = RetrievalQAChain.fromLLM(model, retriever);

Agents - Dynamic Decision Making

import { initializeAgentExecutorWithOptions } from "langchain/agents";
import { Calculator } from "langchain/tools/calculator";

const tools = [new Calculator()];

const agent = await initializeAgentExecutorWithOptions(tools, model, {
agentType: "zero-shot-react-description",
});

const result = await agent.call({
input: "What is 25% of 180?"
});
// Agent decides to use calculator tool

ffmpeg cheat sheet

· 約1分
Mikyan
白い柴犬
# Transform to 3 times play
ffmpeg -i input.mp4 -vf setpts=PTS/3 -af atempo=3 output.mp4

Gitlab CI, Zero to Hero

· 約6分
Mikyan
白い柴犬

.gitlab-ci.yml file is the entry point of GitLab CI/CD, must be placed in your repository root.

Job, Stage, Pipeline

Job: Individual tasks that run commands, build blocks of Gitlab CI pipeline.

Pipeline: The top-level component containing all jobs. However there is no way to directly define a pipeline, user can only define jobs, Gitlab constructs pipeline on:

  • Which jobs match the trigger conditions
  • How those jobs are related

Common Patterns for pipeline separation:

  • by branch
  • by pipeline source
  • by variables

Stage: groups of jobs that run in sequence

Stages are a grouping mechanism for jobs They define execution sequence

GitLab have a default stages definition. Or you can define stages in .gitlab-ci.yml. GitLab just enforces the execution order you specify.

# If you omit the stages: declaration
# GitLab uses these DEFAULT stages:
# - .pre
# - build
# - test
# - deploy
# - .post

stages:
- prepare
- build
- test
- deploy

GitLab Runners

Gitlab runner is a software (agent) that execute your CI/CD jobs

Listener/worker, that constantly polls GitLab for jobs, execute job, report result.

Gitlab Runners are installed on VM/container/server/kubernetes Pod

Type of runners:

  • Shared Runners: Available to all projects
  • Group Runners: Available to all projects in a group
  • Specific Runners: Dedicated to specific projects

Runners use Executors to run your job.

Executor Types:

  • shell-job
  • docker-job
  • k8s-job

default is docker executor

each job runs in a brand new container. for the following reasons:

  • isolation
  • predictability
Pipeline Start

[build-job]
├─ Pull node:16 image
├─ Create new container
├─ Run scripts
└─ Destroy container ❌

[test-job]
├─ Pull node:16 image (cached)
├─ Create NEW container
├─ Run scripts (no files from build!)
└─ Destroy container ❌

Pipeline End

Sharing data between jobs: artifacts

Gitlabe automatically clones your repository before any job.

stages:
- install
- build
- test
- deploy

install-deps:
stage: install
image: node:16
script:
- npm ci
- npm audit
artifacts:
paths:
- node_modules/
expire_in: 1 day

build-app:
stage: build
image: node:16
script:
- npm run build
dependencies:
- install-deps # Gets node_modules/
artifacts:
paths:
- dist/
- node_modules/

test-unit:
stage: test
image: node:16 # Fresh container!
script:
- npm test
dependencies:
- build-app # Gets dist/ and node_modules/

test-e2e:
stage: test
image: cypress/included:10 # Different image, fresh container
services:
- name: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
alias: app
script:
- cypress run --config baseUrl=http://app:3000
dependencies:
- build-app

deploy:
stage: deploy
image: alpine:latest # Fresh container
script:
- apk add --no-cache curl
- curl -X POST $DEPLOY_WEBHOOK
dependencies:
- build-app # Only needs dist/

Cache: Speed optimization (might exist, might not)

Artifacts: guaranteed data transfer between jobs

If Job B needs Job A → B gets A's artifacts If Job B doesn't reference A → B can NEVER get A's artifacts

Cache is a way to preserve files between pipeline runs to speed up the jobs. cache is about preserving data across different pipelines.

Basic Job Configuration

Script types:

  • script: the only required field in a job. containing main job logic
    • commands run in sequence
    • if any command fails, job fails
    • runs in the project directory
    • has access to all CI variables
  • before_script: run before the main script, Perfect for environment setup
  • after_script: run after the main script, even if the job fails

why we need three scripts:

  • separation of concerns
  • guaranteed cleanup
  • error handling simplicity

Configurations control when jobs run

  • only/except: legacy, but still in use, specify the branch

  • when: specify the execution timing, can be used standalone or within rules

    • on_success: run if all previous succeeded
  • rules (recomended):

    • changes: File Changes:
    • exists: File existence
    • allow_failure: in rules
    • variables: Set variables in rules
  • trigger: use to start a completely separate pipeline. either in the same project or a different project

job:
rules:
# Branch conditions
- if: '$CI_COMMIT_BRANCH == "main"'
- if: '$CI_COMMIT_BRANCH != "main"'
- if: '$CI_COMMIT_BRANCH =~ /^feature-/'

# Tag conditions
- if: '$CI_COMMIT_TAG'
- if: '$CI_COMMIT_TAG =~ /^v\d+/'

# Pipeline source
- if: '$CI_PIPELINE_SOURCE == "push"'
- if: '$CI_PIPELINE_SOURCE == "web"'
- if: '$CI_PIPELINE_SOURCE == "schedule"'

# Complex conditions
- if: '$CI_COMMIT_BRANCH == "main" && $DEPLOY_ENABLED == "true"'
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main" || $CI_MERGE_REQUEST_LABELS =~ /urgent/'

Keywords:

stage: image: specify which docker image to use services: Helper containers variables: environment variables artifacts: save job output dependencies: control artifact flow needs: DAG (Directed Acyclic Graph) rules: smart conditions (better than only / except) when: execution conditions cache: speed up pipelines retry: handle flaky jobs timeout: prevent hanging allow_failure: non-blocking failures coverage: extract coverage environment: track deployments parallel: multiple instances trigger: pipeline control only

tags

Job Status Types:

pending/running/success/failed/skipped/manual

failed: script returned non-zero exit code skipped means the didn't meet conditions manual: waiting for manual trigger

CI/CD variables:

key-value pairs available during job execution. Environment variables on steroids

  1. Predefined variables (GitLab Provides)
  • CI_PROJECT_NAME
  • CI_COMMIT_BRANCH
  • CI_COMMIT_SHA
  • CI_COMMIT_MESSAGE
  • CI_PIPELINE_ID
  • CI_PIPELINE_SOURCE
  • CI_JOB_ID
  • CI_JOB_NAME
  • CI_RUNNER_ID
  • CI_RUNNER_TAGS
  • CI_PROJECT_URL
  • CI_PIPELINE_URL
  • CI_JOB_URL
deploy:
script:
# Different behavior for different triggers
- |
if [ "$CI_PIPELINE_SOURCE" == "merge_request_event" ]; then
echo "This is a merge request"
fi

# Use commit info
- docker build -t myapp:$CI_COMMIT_SHORT_SHA .

# Conditional logic
- |
if [ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]; then
echo "On default branch (usually main)"
fi

Variables can be defined at multiple levels, Higher level wins.

Job -> Pipeline -> Project -> Group -> Instance -> Predefined

  • protected variables
  • masked variables
  • file variables
  • variable expansion
build:
variables:
VERSION: "1.0.0"
IMAGE_TAG: "myapp:$VERSION" # Expands to myapp:1.0.0

Conditional variables

deploy:
script:
- echo "Deploying to $ENVIRONMENT"
rules:
- if: $CI_COMMIT_BRANCH == "main"
variables:
ENVIRONMENT: production
REPLICAS: "5"
- if: $CI_COMMIT_BRANCH == "develop"
variables:
ENVIRONMENT: staging
REPLICAS: "2"

Dynamic variables

build:
script:
# Create variables during job
- export BUILD_TIME=$(date +%Y%m%d-%H%M%S)
- echo "VERSION=$CI_COMMIT_SHORT_SHA-$BUILD_TIME" >> build.env
artifacts:
reports:
dotenv: build.env # Pass to next jobs

test:
needs: [build]
script:
- echo "Testing version: $VERSION" # From build.env

Needs

let you create DAG instead of rigid stage-based pipelines.

PostgreSQLのRow Level Security紹介

· 約1分
Mikyan
白い柴犬

PostgreSQLのRow Level Securityを使って、DBレベルで、権限制限できて、より安全なシステム開発できる。

例えば、UserProfileのセレクト、Updateクエリをuser.idで制限したら、他人の情報の誤操作を防げます。

Row Level Securityとは

名前通り、PostgreSQLデータベースのテーブルPolicyの設定によって、行ごとのR/W権限設定できる。

SupabaseはこのRLSを活用して、

https://www.youtube.com/watch?v=vZT1Qx2xUCo&t=691s

PostgreSQLのRow Level Security紹介

· 約1分
Mikyan
白い柴犬

PostgreSQLのRow Level Securityを使って、DBレベルで、権限制限できて、より安全なシステム開発できる。

例えば、UserProfileのセレクト、Updateクエリをuser.idで制限したら、他人の情報の誤操作を防げます。

Row Level Securityとは

名前通り、PostgreSQLデータベースのテーブルPolicyの設定によって、行ごとのR/W権限設定できる。

SupabaseはこのRLSを活用して、

https://www.youtube.com/watch?v=vZT1Qx2xUCo&t=691s